使用成员模板函数显式模板实例化
我有一个带模板成员函数的模板类。我想明确地实例化这个类,以避免剧烈的编译放缓。我正在使用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的&)将不被定义所有可能的显式实例化,因此编译器会抛出不支持它的类型。
这段代码在visual studio中编译(没有内联前面的模板,这是一个gcc特定的扩展)。有人可以告诉我如何让这段代码片段编译?
UPDATE: 这是我的错误:
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
我很困惑这个:
I don't want to use a catch-all:
template class Test<int, double>
because the overload get(const int&) will not be defined for all possible explicit instantiations and hence the compiler will throw a fit for types which dont support it.
一个明晰的专业化,不影响其他专业化的语义。
重载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
在gcc中,如果使用内联实例化,则不会对成员函数进行初始化,并且可以根据需要进行操作。如果在实例化时不使用“内联”,则模板的所有成员都将被实例化。参考:http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html 对不起,不好的措辞,我想能够通过使用内联实例化每个必要的成员,并尝试这样做时得到错误。 – Venkatesan 2010-08-30 06:39:48
@Venkatesan:“每个必要的成员”?根据您链接的页面,没有成员被实例化。 – Potatoswatter 2010-08-30 06:54:14
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顺便说一句,但你可以用0/NULL替换。
14.7.3/2:“对于成员模板,应声明一个显式的特殊化,在其封闭类或封闭类模板所属的名称空间中。” 此外,您完全删除了显式实例,这有助于回避问题。 – Potatoswatter 2010-08-28 18:49:24
'foo'是为了'Test'吗?你能发布实际的错误和它所指的行吗? – 2010-08-28 07:14:09
我键入foo以方便打字。实际的错误是: g ++ -c -o template.o template.cpp template.cpp:14:error:ambiguous template specialization'get 'for'void * Test :: get(const int&)' template .cpp:7:error:candidate are:void * Test :: get(const int&)[with T = int,S = double] template.cpp:6:error:template void * Test :: get(const T1&)[与T1 = T1,T = INT,S =双倍] –
Venkatesan
2010-08-28 07:23:48
糟糕,我没有看到'typedef',对不起。 – 2010-08-28 07:26:06