简体   繁体   English

没有默认功能的C ++模板专业化

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM