我有一个带有模板成员函数的模板类。我想显式实例化该类,以避免激烈的编译减速。我正在使用g ++ 4.1.2。我从编译器得到模糊的模板特化错误。这是最短的代码,它将重现问题:
template <class T, class S >
class Test
{
public:
template< typename T1 >
void* get( const T1& );
void* get(const int& ); //Specialization of the above
};
typedef Test<int, double> foo;
//instantiate
inline template class Test<int, double>;
template void* foo::get(int const&);
我不想使用全能:
template class Test<int, double>
因为不会为所有可能的显式实例化定义重载get(const int&amp;),因此编译器会抛出不支持它的类型。
此代码在visual studio中编译(没有内联前置模板,这是gcc特定的扩展)。有人可以告诉我如何编译这段代码吗?
更新: 这是我得到的错误:
g++ -c -o template.o template.cpp
template.cpp:14: error: ambiguous template specialization ‘get<>’ for ‘void* Test<int, double>::get(const int&)’
template.cpp:7: error: candidates are: void* Test<T, S>::get(const int&) [with T = int, S = double]
template.cpp:6: error: template<class T1> void* Test::get(const T1&) [with T1 = T1, T = int, S = double]
UPDATE2: 感谢您的解决方案,它不会编译。课堂内不允许进行专业化。错误是:
g++ -c -o template.o template.cpp
template.cpp:7: error: explicit specialization in non-namespace scope ‘class Test<T, S>’
template.cpp:7: error: enclosing class templates are not explicitly specialized
template.cpp:8: error: ‘get’ is not a template function
template.cpp: In instantiation of ‘void* Test<T, S>::get(const T1&) [with T1 = int, T = int, S = double]’:
template.cpp:15: instantiated from here
template.cpp:15: error: explicit instantiation of ‘void* Test<T, S>::get(const T1&) [with T1 = int, T = int, S = double]’ but no definition available
make: *** [template.o] Error 1
答案 0 :(得分:2)
我对此感到困惑:
我不想使用全能:
template class Test<int, double>
因为重载get(const int&amp;) 将不会为所有可能的定义 明确的实例化,因此 编译器将适合类型 不支持它。
一个专业化的显式性不会影响其他专业化的语义。
重载get(const int&)
只是一个成员函数,它将像其他任何一样实例化显式和隐式特化。
显式实例化只能减慢编译器的速度。它最多只处理一次实例化。可以忽略隐式实例化的未使用部分,但是通过显式实例化,您将强制它处理整个事务。无论如何,并非单个实例化可能需要花费大量时间。
要在代码中运行错误:
template <class T, class S > // arguments unused
class Test
{
public:
template< typename T1 >
void* get( const T1& );
void* get(const int& ); // overload of the above
};
typedef Test<int, double> foo;
// illegal to instantiate a template before its members are defined
inline template class Test<int, double>; // "inline template" is meaningless
template void* foo::get(int const&); // typedef name "foo" cannot be used here
/* ^ illegal to explicitly instantiate a member of an already explicitly
instantiated template */
更新
错误是由非模板重载导致的,而不是优先于成员模板。
不幸的是,您cannot explicitly specialize是模板父级的成员模板。该问题的解决方法是部分专门化,但由于您有一个功能模板,因此无效。
解决方法#2是SFINAE。
#include <boost/enable_if.hpp>
#include <boost/type_traits.hpp>
template< typename T1 >
boost::disable_if< boost::is_same<T1,int>, void* >::type
get( const T1& ); // "turn off" declaration if in conflict
void* get(const int& ); // unambiguous overload of the above
如果你不能使用Boost,
template< class T >
struct disable_if_int { typedef void *type; };
template<>
struct disable_if_int<int> {};
...
template< typename T1 >
disable_if_int< T1 >::type get( const T1& );
void* get(const int& ); // unambiguous overload of the above
答案 1 :(得分:0)
template <class T, class S >
class Test
{
public:
template< typename T1 >
void* get( const T1& ) { return nullptr; }
template <>
void* get<int>(const int& ) { return nullptr; } //Specialization of the above
};
typedef Test<int, double> foo;
int main() {
foo lols;
void* innit = lols.get(1);
void* bruv = lols.get("yocakes");
}
这对VS2010的编译很好。 nullptr是c ++ 0x btw,但你可以用0 / NULL替换。