使用成员模板函数显式模板实例化
我有一个带有模板成员函数的模板类。我想显式实例化该类以避免编译速度急剧下降。我正在使用 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 特定的扩展)。有人可以解释一下我如何编译这个代码片段吗?
更新: 这是我得到的错误:
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 have a template class with a template member function. I want to explicitly instantiate the class to avoid a drastic compilation slowdown. I am using g++ 4.1.2. I get ambiguous template specialization errors from the compiler. This the shortest code which will reproduce the problem:
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&);
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.
This code compiles in visual studio (without the inline preceeding template, which is a gcc specific extenstion). Can somebody please throw some light into how I get this code fragment to compile?
UPDATE:
This is the error I get:
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:
Thanks for the solution, it does not compile though. Specializations are not allowed inside a class. The error is:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我对此感到困惑:
一种专业化的显式性不会影响其他专业化的语义。
重载
get(const int&)
只是一个成员函数,它将像其他任何函数一样被实例化以进行显式和隐式特化。显式实例化只会减慢编译器的速度。它最多只处理每个实例一次。隐式实例化中未使用的部分可能会被忽略,但通过显式实例化,您将强制它处理整个事情。无论如何,单个实例化可能不会花费大量时间。
要运行代码中的错误:
更新:
该错误是由于非模板重载不具有高于成员模板的优先级而导致的。
不幸的是,您无法显式专业化模板的成员模板父母。该问题的解决方法是部分专业化,但这不起作用,因为您有一个函数模板。
解决方法#2 是SFINAE。
如果你不能使用Boost,
...
I'm confused by this:
Explicitness of one specialization does not affect the semantics of other specializations.
The overload
get(const int&)
is simply a member function, and it will be instantiated for explicit and implicit specializations like any other.Explicit instantiation can only slow down the compiler. It only processes each instantiation at most once. Unused parts of an implicit instantiation may be ignored, but by explicitly instantiating, you are forcing it to handle the whole thing. Not that a single instantiation is likely to take a measurable amount of time, anyway.
To run through errors in the code:
Update:
The error results from the non-template overload not having priority over the member template.
Unfortunately, you cannot explicitly specialize a member template of a template parent. The workaround at that question is to partially specialize, but that won't work because you have a function template.
Workaround #2 is SFINAE.
If you can't use Boost,
...
这对我来说在 VS2010 上编译得很好。 nullptr 是 c++0x 顺便说一句,但你可以用 0/NULL 替换。
This compiles just fine for me on VS2010. nullptr is c++0x btw, but you could just replace with 0/NULL.