为类模板

时间:2018-01-08 14:48:17

标签: c++ templates syntax

我有一个模板类(或者它是一个类模板?),它有许多成员函数。我对所有这些都有定义。我想覆盖其中一个定义,对于T的特定值。我希望我不必为这个特定的T值提供所有成员函数的定义,因为它们都与T的相同。通用T的定义。

我尝试了类似下面的内容,但是我收到链接器错误“...找到一个或多个多重定义的符号”

我使用了错误的语法,或者我正在做一些C ++中根本不允许的事情。

template <typename T>
struct A
{
    void a(T);
    void b(T);
    ...
    void z(T);
};

void A<int>::a(int)
{
    // do something special for this particular template parameter
}

template <typename T>
void A<T>::a(T){}

template <typename T>
void A<T>::b(T){}

...

template <typename T>
void A<T>::z(T){}

具体来说,这是一些导致同样问题的真实代码:

template<typename T>
struct A
{ 
    void f(T);
};

template<> // same linker error with or without this line
void A<int>::f(int)
{
    // something special
}

template<typename T>
void A<T>::f(T)
{
}

4 个答案:

答案 0 :(得分:3)

您几乎是正确的,您只是缺少template<>来表明明确的专业化:

template<>
void A<int>::a(int)
{
}

编辑:以下答案正确指出,如果您希望在标头中使用此实现,则应使用inline说明符。或者,您可以选择将实现移动到源文件, 在这种情况下,您仍应声明头文件中的显式特化。换句话说,它遵循常规的函数定义规则。

答案 1 :(得分:1)

template<> void A<int>::f(int)不再是模板。所以不再inline

你必须在cpp中实现它(并在标题中声明它)

或添加inline以避免具有多个定义(因此在标题中定义)。

template<> inline void A<int>::f(int)
{
    // something special
}

答案 2 :(得分:0)

  

我希望我不必为这个特定的T值提供所有成员函数的定义,因为它们都与通用T的定义相同。

如果您可以使用C ++ 11,可能的解决方案是SFINAE启用/禁用通用或int特定a()版本。

这样的东西
template <typename T>
struct A
 {
   template <typename U = T>
   typename std::enable_if<false == std::is_same<int, U>{}>::type a(T)
    { std::cout << "generic version" << std::endl; }

   template <typename U = T>
   typename std::enable_if<true == std::is_same<int, U>{}>::type a(T)
    { std::cout << "integer version" << std::endl; }

   void b(T) {}
   void z(T) {}
 };

为避免以这种方式使用a()方法

A<float>{}.a<int>();

可以修改std::enable_if的测试,以检查TU是否属于同一类型

   template <typename U = T>
   typename std::enable_if<(false == std::is_same<int, U>{})
                        && (true == std::is_same<T, U>{})>::type a(T)
    { std::cout << "generic version" << std::endl; }

   template <typename U = T>
   typename std::enable_if<(true == std::is_same<int, U>{})
                        && (true == std::is_same<T, U>{})>::type a(T)
    { std::cout << "integer version" << std::endl; }

如果您需要C ++ 98解决方案,可以按如下方式模拟std::is_samestd::enable_if

template <typename, typename>
struct isSame
 { static const bool value = false; };

template <typename T>
struct isSame<T, T>
 { static const bool value = true; };

template <bool, typename>
struct enableIf
 { };

template <typename T>
struct enableIf<true, T>
 { typedef T type; };

可以撰写A struct

template <typename T>
struct A
 {
   template <typename U>
   typename enableIf<(false == isSame<int, U>::value)
                  && (true == isSame<T, U>::value), void>::type a(U)
    { std::cout << "generic version" << std::endl; }

   template <typename U>
   typename enableIf<(true == isSame<int, U>::value)
                  && (true == isSame<T, U>::value), void>::type a(U)
    { std::cout << "integer version" << std::endl; }

   void b(T) {}
   void z(T) {}
 };

另一种可能的C ++ 11解决方案,它不使用SFINAE但是有几种辅助方法,是一种标签调度&#34;一个

template <typename T>
struct A
 {
   void a_helper (T, std::true_type const &)
    { std::cout << "integer version" << std::endl; }

   void a_helper (T, std::false_type const &)
    { std::cout << "generic version" << std::endl; }

   void a (T t)
    { a_helper(t, std::is_same<T, int>{}); }

   void b(T) {}
   void z(T) {}
 }; 

答案 3 :(得分:0)

感谢上面的响应者。我的问题基本上是我错过了关键字内联。这是有效的(释义)

 // in header file:

template <typename T>
struct A
{
    void a(T);
    void b(T);
    ...
    void z(T);
};

template <typename T>
void A<T>::a(T){}

template <typename T>
void A<T>::b(T){}

...

template <typename T>
void A<T>::z(T){}

// in .cpp file:
template <typename T>
inline void A<int>::a(int)
{
    // do something special for this particular template parameter
}