C++ C++;没有默认函数的模板专门化
我有以下代码可以编译并运行良好:C++ C++;没有默认函数的模板专门化,c++,templates,specialization,C++,Templates,Specialization,我有以下代码可以编译并运行良好: template<typename T> T GetGlobal(const char *name); template<> int GetGlobal<int>(const char *name); template<> double GetGlobal<double>(const char *name); 模板 T GetGlobal(常量字符*名称); 模板 int GetGlobal(常量
template<typename T>
T GetGlobal(const char *name);
template<>
int GetGlobal<int>(const char *name);
template<>
double GetGlobal<double>(const char *name);
模板
T GetGlobal(常量字符*名称);
模板
int GetGlobal(常量字符*名称);
模板
双GetGlobal(常量字符*名称);
但是,我想删除“default”函数。也就是说,我想对GetGlobal进行所有调用,其中“t”不是int或double,而是一个错误
例如,GetGlobal()应该是编译时错误
我试图删除默认函数,但正如我想象的那样,我收到了很多错误。。那么,有没有一种方法可以“禁用”它并只允许调用函数的专用版本呢
谢谢 要获取编译时错误,请将其实现为:
template<typename T>
T GetGlobal(const char *name) { T::unimplemented_function; }
// `unimplemented_function` identifier should be undefined
模板
T GetGlobal(const char*name){T::未实现的函数;}
//`unimplemented_function`标识符应未定义
如果使用Boost,则可以使其更加优雅:
template<typename T>
T GetGlobal(const char *name) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }
模板
T GetGlobal(const char*name){BOOST_STATIC_ASSERT(sizeof(T)==0)}
C++标准保证没有sizeof等于0的类型,因此会出现编译时错误
正如他在评论中所建议的那样,最后一项可以缩减为:
template<typename T>
T GetGlobal(const char *name) { char X[!sizeof(T)]; }
模板
T GetGlobal(const char*name){char X[!sizeof(T)];}
我更喜欢第一种解决方案,因为它比其他解决方案提供了更清晰的错误消息(至少在Visual C++中是如此)。我建议不要实际提供实现,只提供方法的简单声明 另一个选项是使用编译时断言。Boost有很多这样的野兽
namespace mpl = boost::mpl;
BOOST_MPL_ASSERT((mpl::or_< boost::same_type<T, double>,
boost::same_type<T, int> >));
namespace-mpl=boost::mpl;
BOOST\u MPL\u ASSERT((MPL::或);
还有它的消息版本对应项,这会有所帮助。如果不实现它,至少会出现链接器错误。如果需要编译时错误,可以使用类模板执行此操作:
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);
}
模板
结构全局代数;
模板
结构全局代数{
静态int GetGlobal(常量字符*名称);
};
模板
结构全局代数{
静态双GetGlobal(常量字符*名称);
};
模板
T GetGlobal(常量字符*名称)
{
返回GlobalGetter::GetGlobal(名称);
}
以下是使用boost的替代技术:
将typedef声明为从属名称
这是因为只有在“T”被替换时,才会对“not”进行名称查找。这与下面给出的示例类似(但合法)
模板
T GetGlobal(常量字符*名称){
typedef typename T::不要调用此函数;
}
使用不完整的返回类型
这种技术不适用于专门化,但适用于重载。其思想是,声明返回不完整类型的函数是合法的,但不调用它:
template <typename T>
class DONT_CALL_THIS_FUNCTION GetGlobal (const char * name);
模板
类不调用此函数GetGlobal(const char*name);
尽管这是一个古老而过时的问题,但值得注意的是,C++11
使用删除的函数解决了这个问题:
template<typename T>
T GetGlobal(const char *name) = delete;
template<>
int GetGlobal<int>(const char *name);
更新
VisualStudio15.9也有同样的错误。使用前面的解决方法。为了使第一个案例在编译时失败,Koper需要一个未声明的函数,而不是未定义的函数。要编译它,唯一的方法就是使它依赖于
T
。类似于T::一些\u肯定是\u未声明的东西\u可能会这样做。(第二个可能可以用char dummy[!sizeof(T)];
模拟)使用unimplemented_函数
比使用T::unimplemented_函数
@Kirill提供更清晰的错误消息(至少在Visual C++中是如此):使用unimplemented_函数
在执行两阶段查找的编译器中不起作用。(目前,VC不这样做。)这样的编译器不会编译模板定义,即使它从未实例化。-1:SBI是正确的。查找标识符时,由于它不是带有从属参数的功能调用(即ADL调用),因此它将是一个错误。请修正这个例子——并收回你的观点!:)类似这样的模板结构没有定义:mpl::false{};模板T GetGlobal(char const*name){BOOST_MPL_ASSERT((未定义))}
将给出一些不错的错误:。知道模板函数前向声明不会产生编译器错误的原因吗,而模板类转发声明确实如此?如果您的专门化比“int”和“double”多得多,那么编写的内容就太多了。什么是GlobalGetter(name)
?建造师?在GlobalGetter
和GlobalGetter
@xtofl:中没有带单参数的构造函数,因为编译函数调用只需要函数模板声明。(而对于类,您需要定义。)@Kiril:您没有编写函数模板专门化,而是为只包含一个stat函数的类模板编写专门化。是的,需要再敲几下键盘才能打字,但没那么糟。但是,您的第二个解决方案(使用STATIC\u ASSRT
的解决方案)也是我喜欢的。这是最好的解决方案,谢谢!它可能也与此相关:llvm 5.0和3.9已经修复了此错误。
template<typename T>
T GetGlobal(const char *name) = delete;
template<>
int GetGlobal<int>(const char *name);
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);