У меня есть шаблон класса, а внутри него статический метод, входным аргументом которого является сам класс. Например:
#include <iostream>
template <typename T>
class A
{
public:
A( const T& t ) : val(t) {}
static bool IsValid( const A<T>& a ) { return (bool)a.val; }
private:
T val;
};
int main()
{
A<int> a( 5 );
std::cout << A<int>::IsValid( a ) << "\n"; // <---
return 0;
}
Я считаю, что строку 18 (отмеченную <---
) очень неудобно писать снова и снова.
Интересно, почему я не могу назвать свой метод как A::IsValid( a )
, учитывая, что тип T
можно легко вывести из входных данных a
? Есть ли способ написать это по-другому, чтобы это было возможно?
Ближайший вопрос SO, который я нашел, был: Как вызвать статический метод шаблона класса без указания экземпляра?, но этот вопрос по своей сути отличается, поскольку у него нет аргументов, из которых можно было бы вывести тип.
вы можете сделать это бесплатной функцией
В шаблонах классов могут быть произвольные функции, но у вас есть параметр того же типа, что и у класса, но это верно не для каждой функции.
Зачем писать A::IsValid(a)
, если можно написать a.isValid()
?
@Botje: потому что в реальном коде аргумент a
на самом деле имеет тип shared_ptr<A<T>>
, поэтому первое, что делает IsValid
, — это проверяет сам указатель на nullptr
.
Почему isValid
— статическая функция? По названию я бы заподозрил, что это функция-член. Также аргументы выглядят точно так же, как this
. Поэтому мне интересно: почему вы вообще сделали эту функцию статической? Ваш комментарий выше - плохое объяснение. Ваш способ адресации nullptr является излишним.
Нет, это невозможно.
Сначала учтите, что только CTAD (вывод аргументов шаблона класса) выводит аргументы шаблона для шаблонов классов, которые собираются быть созданы на основе типов переданных аргументов функции. Однако, когда вы вызываете статический метод, ни один объект не создается.
Далее учтите, что A<U>
можно специализировать на наличии члена IsValid(const A<V>&)
. Другими словами, между T
типа аргумента IsValid(const A<T>&)
и T
в A<T>::IsValid
не существует отношения 1 к 1. Например:
template <> class A<double> {
static bool IsValid(const A<int>& a) { return true; }
};
Теперь не было бы возможности определить, какой экземпляр A
требуется при вызове A::IsValid( A<int>{} )
. Это вызов метода A<int>
или A<double>
? Имеет ли значение, что этот метод является членом класса? Это подводит меня к...
Вы можете написать бесплатную функцию:
auto IsValid(const auto& a) {
return decltype(a)::IsValid(a);
}
Или сделайте это нестатической функцией-членом.
потому что это невозможно вывести.
A<T>
есть методIsValid(A<T>)
, но обратное неверно.IsValid(A<U>)
может быть методом некоторыхA<V>
.