我有一个模板类(或者它是一个类模板?),它有许多成员函数。我对所有这些都有定义。我想覆盖其中一个定义,对于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)
{
}
答案 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
的测试,以检查T
和U
是否属于同一类型
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_same
和std::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
}