我试图通过它的模板参数的类型特征来专门化模板化类的成员函数,但我的前向声明显然是不正确的。有一个简单的解决方法吗?
#include <type_traits>
template <typename T>
class TTest{
public:
T data;
// edited to comment this out, template<typename U>
bool operator !=(const TTest& other) const;
};
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, bool>::type
TTest<T>::operator !=(const TTest<T>& other) const{
return true;
}
template<typename T>
bool TTest<T>::operator !=(const TTest<T>& other) const{
return false;
}
int main(){
TTest<size_t> t1;
TTest<int> t2;
}
Clang告诉我:
templateTest.cpp:13:11: error: out-of-line definition of 'TTest::operator!='
differs from the declaration in the return type
TTest<T>::operator !=(const TTest<T>& other) const{
^
templateTest.cpp:8:8: note: previous declaration is here
bool operator !=(const TTest& other) const;
^
1 error generated.
答案 0 :(得分:4)
似乎整个enable_if
shebang是函数签名的一部分(或者我并不真正理解错误)。如果将其更改为
template <typename T>
class TTest{
public:
T data;
template<typename U>
typename std::enable_if<std::is_unsigned<U>::value, bool>::type
operator !=(const TTest<U>& other) const;
template<typename U>
typename std::enable_if<not std::is_unsigned<U>::value, bool>::type
operator !=(const TTest<U>& other) const;
};
template <typename T>
template <typename U>
typename std::enable_if<std::is_unsigned<U>::value, bool>::type
TTest<T>::operator !=(const TTest<U>&) const{
return true;
}
template <typename T>
template <typename U>
typename std::enable_if<not std::is_unsigned<U>::value, bool>::type
TTest<T>::operator !=(const TTest<U>&) const{
return false;
}
Live demo。当然,如果您将这些运算符内联定义,则重复性会降低很多。
更好的方法可能是根据T
的特征调度到运算符逻辑的不同私有实现。这将从您的代码中删除所有SFINAE详细程度。
template <typename T>
class TTest{
public:
T data;
bool operator!=(const TTest& other) const
{
return not_equal_to(other, typename std::is_unsigned<T>::type());
}
private:
bool not_equal_to(TTest const&, std::true_type) const
{
return true;
}
bool not_equal_to(TTest const&, std::false_type) const
{
return false;
}
};
答案 1 :(得分:1)
您声明了类模板的成员函数模板,并且您尝试将其专门化为成员函数。那不会飞。此外,返回类型不同,但最终评估相同的事情。
我不知道你试图尝试什么,因为甚至没有推导出成员函数模板的类型U
(你的意思是参数类型为TTest<U>
吗?)。如果你想根据特征专门化你的成员,我认为你要么需要重载运算符,要么使用不同的方法(例如,将实现委托给专门的类模板):
#include <iostream>
#include <type_traits>
template <typename T>
class TTest{
public:
T data;
template<typename U>
typename std::enable_if<!std::is_unsigned<U>::value, bool>::type
operator !=(const TTest<U>& other) const;
template<typename U>
typename std::enable_if<std::is_unsigned<U>::value, bool>::type
operator !=(const TTest<U>& other) const;
};
template <typename T>
template<typename U>
typename std::enable_if<!std::is_unsigned<U>::value, bool>::type
TTest<T>::operator !=(const TTest<U>& other) const {
return true;
}
template <typename T>
template<typename U>
typename std::enable_if<std::is_unsigned<U>::value, bool>::type
TTest<T>::operator !=(const TTest<U>& other) const {
return false;
}
int main(){
TTest<unsigned int> t1;
TTest<int> t2;
std::cout << std::boolalpha
<< "t1 != t1: " << (t1 != t1) << '\n'
<< "t1 != t2: " << (t1 != t2) << '\n'
<< "t2 != t1: " << (t2 != t1) << '\n'
<< "t2 != t2: " << (t2 != t2) << '\n';
}
答案 2 :(得分:1)
标签调度是干净的方法:
template <typename T>
class TTest{
bool not_equal( const ITest& other, std::true_type /* is unsigned */ ) const;
bool not_equal( const ITest& other, std::false_type /* is unsigned */ ) const;
public:
T data;
bool operator !=(const TTest& other) const {
return not_equal( other, std::is_unsigned<T>() );
}
};
现在只需实现两个TTest<T>::not_equal
重载。只有实际为给定T
调用的那个将被编译为基本解析。