我有以下编译并运行良好的代码:

template<typename T>
T GetGlobal(const char *name);

template<>
int GetGlobal<int>(const char *name);

template<>
double GetGlobal<double>(const char *name);

但是我想删除<!> quot; default <!> quot;功能。也就是说,我想对GetGlobal进行所有调用<!> lt; t <!> gt;其中't'不是int或double错误。

例如,GetGlobal <!> lt; char <!> gt;()应该是编译时错误。

我试图删除默认函数,但是,正如我想象的那样,我收到了很多错误..那么有没有办法<!> quot; disable <!> quot;它并且只允许调用该函数的专用版本?

谢谢!

有帮助吗?

解决方案

要获得编译时错误,请将其实现为:

template<typename T>
T GetGlobal(const char *name) { T::unimplemented_function; }
// `unimplemented_function` identifier should be undefined

如果你使用Boost,你可以使它更优雅:

template<typename T>
T GetGlobal(const char *name) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }

C ++ Standard保证不存在sizeof等于0的类型,因此您将收到编译时错误。

正如 sbi 在他的评论中建议的那样,最后可以缩减为:

template<typename T>
T GetGlobal(const char *name) { char X[!sizeof(T)]; }

我更喜欢第一种解决方案,因为它提供了比其他解决方案更清晰的错误消息(至少在Visual C ++中)。

其他提示

虽然这是一个陈旧且过时的问题,但值得注意的是C++11使用已删除的函数解决了这个问题:

template<typename T>
T GetGlobal(const char *name) = delete;

template<>
int GetGlobal<int>(const char *name);

<强>更新

这不会在MacOS llvm 8下编译。 这是由于仍然悬挂4年的缺陷(参见此错误报告) )。

以下解决方法适合该问题(使用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);

<强>更新

Visual Studio 15.9有相同的bug。使用以前的解决方法。

如果你没有实现它,你至少会得到一个链接器错误。如果您想要编译时错误,可以使用类模板执行此操作:

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);
}

我建议不要实际提供一个实现,只是声明该方法。

另一种选择是使用编译时断言。 Boost有很多这样的野兽。

namespace mpl = boost::mpl;
BOOST_MPL_ASSERT((mpl::or_< boost::same_type<T, double>,
                            boost::same_type<T, int> >));

还有它的消息版本副本,这将有所帮助。

scroll top