按类型专门设计模板类成员函数

时间:2014-01-08 20:13:01

标签: c++ templates specialization

我试图通过它的模板参数的类型特征来专门化模板化类的成员函数,但我的前向声明显然是不正确的。有一个简单的解决方法吗?

#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.

3 个答案:

答案 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;
  }
};

Live demo

答案 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调用的那个将被编译为基本解析。