【发布时间】:2017-03-23 15:38:48
【问题描述】:
我有这样的代码:
template< class T >
struct Value
{
/* quite a lot of other functions which I do not want to specialize, too */
void print( void );
};
template<> void Value< short int >::print() { std::cout << "is integral" << std::endl; }
template<> void Value< int >::print() { std::cout << "is integral" << std::endl; }
template<> void Value< long int >::print() { std::cout << "is integral" << std::endl; }
template<> void Value< unsigned short int >::print() { std::cout << "is integral" << std::endl; }
template<> void Value< unsigned int >::print() { std::cout << "is integral" << std::endl; }
template<> void Value< unsigned long int >::print() { std::cout << "is integral" << std::endl; }
template<> void Value< float >::print() { std::cout << "is floating point" << std::endl; }
template<> void Value< double >::print() { std::cout << "is floating point" << std::endl; }
template<> void Value< long double >::print() { std::cout << "is floating point" << std::endl; }
template< class T > void Value<T>::print() { std::cout << "unsupported type" << std::endl; }
int main( void )
{
Value< float >().print();
Value< double >().print();
Value< short >().print();
Value< char >().print();
}
输出:
is floating point
is floating point
is integral
unsupported type
我想更改它以减少代码重复,特别是因为代码主体比简单的std::cout 长得多。为了说明我想走的方向,想到的最简单的想法是使用宏:
#define TMP(T) \
template<> void Value<T>::print() { std::cout << "is integral" << std::endl; }
TMP( short int )
TMP( int )
TMP( long int )
TMP( unsigned short int )
TMP( unsigned int )
TMP( unsigned long int )
#undef TMP
#define TMP(T) \
template<> void Value<T>::print() { std::cout << "is floating point" << std::endl; }
TMP( float )
TMP( double )
TMP( long double )
#undef TMP
但我想使用 C++11 模板魔法让它工作。我已经尝试过使用std::enable_if,但我就是无法让它工作。例如。这个
template< class T >
void Value<
typename std::enable_if< std::is_integral<T>::value, T >::type
>::print( void )
{
std::cout << "is integral" << std::endl;;
}
给我
test.cpp:26:24: error: invalid use of incomplete type ‘struct Value<typename std::enable_if<std::is_integral<_Tp>::value, T>::type>’
>::type >::print( void )
^
test.cpp:14:8: error: declaration of ‘struct Value<typename std::enable_if<std::is_integral<_Tp>::value, T>::type>’
struct Value
并在返回类型上使用std::enable_if:
template< class T >
typename std::enable_if< std::is_integral<T>::value, void >::type
Value<T>::print( void )
{
std::cout << "is integral" << std::endl;;
}
给我:
test.cpp:41:1: error: prototype for ‘typename std::enable_if<std::is_integral<_Tp>::value, void>::type Value<T>::print()’ does not match any in class ‘Value<T>’
Value<T>::print( void )
^
test.cpp:16:17: error: candidate is: static void Value<T>::print()
static void print( void );
当然已经有很多类似的问题了:
- http://www.cplusplus.com/forum/beginner/151879/
- match multiple types for template specialization resolution
-
Template specialization for multiple types
- How to do one explicit specialization for multiple types?
但它们通常是关于简单函数的,而不是模板类的方法。而且他们通常不会像我想要的那样严格分开声明和定义。
This questions 听起来很相似,但它不是针对 struct/class 模板参数,而是针对另一个模板参数专门化该方法。
由于上述错误,我似乎无法将答案应用于我的具体问题。此外,我不想专门化整个类,因为该类本身共享许多对所有类型 T 都相同的方法。我不想用一个复制粘贴代码换另一个。
解释为什么会出现两条错误消息的奖励。我打破了什么规则。在我看来,...::type 似乎根本没有被 T 或 void 取代。
【问题讨论】:
-
我认为第一种情况的错误在于它实际上不是值的模板专业化:
A function with the same name and the same argument list as a specialization is not a specializationen.cppreference.com/w/cpp/language/template_specialization