为类模板的单个成员定义专用化
define a specialization for a single member of a class template
我有一个包含许多成员函数的模板类(或者它是一个类模板?(。我有所有这些的定义。我想覆盖其中一个定义,对于 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)
{
}
你几乎是对的,你只是缺少template<>
来表明明确的专业化:
template<>
void A<int>::a(int)
{
}
编辑:下面的答案正确地指出,如果要在标头中包含此实现,则应使用inline
说明符。或者,您可以选择将实现移动到源文件,在这种情况下,您仍应在头文件中声明显式专用化。换句话说,它遵循常规函数定义规则。
template<> void A<int>::f(int)
不再是模板。所以不再inline
.
你必须在 cpp 中实现它(并在标头中声明它(
或添加inline
以避免有多个定义(因此在标题中定义(。
template<> inline void A<int>::f(int)
{
// something special
}
感谢上面的回复者。我的问题本质上是我缺少内联关键字。这是有效的(释义(
// 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
}
我希望我不必为 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,而是使用几个辅助方法,是"标签调度"一个
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) {}
};
- 类模板静态数据成员定义/声明/初始化
- 默认移动成员定义为已删除,而未定义特殊成员?
- 条件C++类成员定义
- 将类类型成员定义为公共和私有之间有什么区别?
- 有没有办法为静态对象成员定义一个符合开关标准的常量?
- C 不能将带有父类指针作为类型的静态模板成员定义引用
- 如何在 .cpp 文件中为私有类成员定义 friend 运算符<<而不是在标头中
- 为类模板的单个成员定义专用化
- 使用命名空间进行函数成员定义
- C 类静态结构成员定义
- C 替代成员定义
- C++:如何将数据成员定义为 const
- 模板超类的静态成员定义
- 如何为联合成员定义typedef
- 为类模板的枚举成员定义 std::hash
- 在越界成员定义的类型说明符中是否可以省略typename
- 更改成员定义的顺序会破坏内存
- 为什么不允许将类成员定义的' static '关键字放在命名空间范围内?
- 我是否应该在将实现委托给子类的类中包含成员定义?
- 在非限定id后的静态数据成员定义中使用的名称