[英]C++ template specialization without default function
I have the following code that compiles and works well: 我有以下编译和运行良好的代码:
template<typename T>
T GetGlobal(const char *name);
template<>
int GetGlobal<int>(const char *name);
template<>
double GetGlobal<double>(const char *name);
However I want to remove the "default" function. 但是我想删除“默认”功能。 That is, I want to make all calls to GetGlobal<t> where 't' is not an int or a double an error.
也就是说,我想对GetGlobal <t>进行所有调用,其中't'不是int或double错误。
For example, GetGlobal<char>() should be a compile time error. 例如,GetGlobal <char>()应该是编译时错误。
I tried to just delete the default function, but, as I imagined, I received a lot of errors.. So is there a way to "disable" it and allow calls only to the specialized versions of the function? 我试图删除默认函数,但是,正如我想象的那样,我收到了很多错误。那么有没有办法“禁用”它并允许只调用函数的专用版本?
Thanks! 谢谢!
To get a compile-time error implement it as: 要获得编译时错误,请将其实现为:
template<typename T>
T GetGlobal(const char *name) { T::unimplemented_function; }
// `unimplemented_function` identifier should be undefined
If you use Boost you could make it more elegant: 如果你使用Boost,你可以使它更优雅:
template<typename T>
T GetGlobal(const char *name) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }
C++ Standard guarantees that there is no such type which has sizeof equal to 0, so you'll get a compile-time error. C ++ Standard保证不存在sizeof等于0的类型,因此您将得到编译时错误。
As sbi suggested in his comments the last could be reduced to: 正如sbi在他的评论中所建议的那样,最后可以减少到:
template<typename T>
T GetGlobal(const char *name) { char X[!sizeof(T)]; }
I prefer the first solution, because it gives more clear error message (at least in Visual C++) than the others. 我更喜欢第一种解决方案,因为它提供了比其他解决方案更清晰的错误消息(至少在Visual C ++中)。
Though it is an old and outdated question, it may worth noting that C++11
had solved this issue using deleted functions: 虽然这是一个陈旧且过时的问题,但值得注意的是
C++11
使用已删除的函数解决了这个问题:
template<typename T>
T GetGlobal(const char *name) = delete;
template<>
int GetGlobal<int>(const char *name);
UPDATE UPDATE
This will not compile under MacOS llvm 8
. 这不会在
MacOS llvm 8
下编译。 It is due to a still hanging 4 years old defect (see this bug report ). 这是由于一个仍然悬挂4年的缺陷(见这个错误报告 )。
The following workaround will fit the issue (using a static_assert
construct). 以下解决方法将适合该问题(使用
static_assert
构造)。
template<typename T>
T GetGlobal(const char *name) {
static_assert(sizeof(T) == 0, "Only specializations of GetGlobal can be used");
}
template<>
int GetGlobal<int>(const char *name);
UPDATE UPDATE
Visual studio 15.9 has the same bug. Visual Studio 15.9有同样的bug。 Use the previous workaround for it.
使用以前的解决方法。
If you don't implement it, you'll at least get a linker error. 如果你没有实现它,你至少会得到一个链接器错误。 If you want a compile-time error, you could do this with class templates:
如果您想要编译时错误,可以使用类模板执行此操作:
template<typename T>
struct GlobalGetter;
template<>
struct GlobalGetter<int> {
static int GetGlobal(const char *name);
};
template<>
struct GlobalGetter<double> {
static double GetGlobal(const char *name);
};
template<typename T>
T GetGlobal(const char *name)
{
return GlobalGetter<T>::GetGlobal(name);
}
I would suggest not to actually provide an implementation, just a bare declaration of the method. 我建议不要实际提供一个实现,只是一个方法的声明。
The other option would be to use a compile-time assert. 另一种选择是使用编译时断言。 Boost has a number of such beasts.
Boost有很多这样的野兽。
namespace mpl = boost::mpl;
BOOST_MPL_ASSERT((mpl::or_< boost::same_type<T, double>,
boost::same_type<T, int> >));
There is also its message version counterpart, which would help. 还有它的消息版本对应,这将有所帮助。
The following are alternative techniques to using boost: 以下是使用boost的替代技术:
Declare a typedef to a dependent name 将typedef声明为依赖名称
This works because name lookup for DONT only occurs when 'T' has been replaced. 这是有效的,因为DONT的名称查找仅在替换'T'时发生。 This is a similar (but legal) version of the example given by Kirill
这是Kirill给出的示例的类似(但合法)版本
template <typename T>
T GetGlobal (const char * name) {
typedef typename T::DONT CALL_THIS_FUNCTION;
}
Use an incomplete return type 使用不完整的返回类型
This technique doesn't work for specializations, but it will work for overloads. 此技术不适用于专业化,但它适用于重载。 The idea is that its legal to declare a function which returns an incomplete type, but not to call it:
这个想法是声明一个返回不完整类型但不调用它的函数的合法性:
template <typename T>
class DONT_CALL_THIS_FUNCTION GetGlobal (const char * name);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.