从这个问题Why should I avoid std::enable_if in function signatures看来,我应该能够写出
#include <type_traits>
#include <iostream>
enum Class {
Primary,
Secondary
};
template<Class C>
class Entity {
public:
template<typename Cls = C, typename Sec = Secondary, std::enable_if<std::is_same<Cls, Sec>::value>::type = 0>
void onlyLegalForSecondaryEntities() {
std::cout << "Works" << std::endl;
}
};
int main() {
Entity<Secondary> e;
e.onlyLegalForSecondaryEntities();
return 0;
}
但是这导致编译错误prog.cpp:13:7: note: template argument deduction/substitution failed
如何编译此代码?
答案 0 :(得分:3)
您对Class
使用enum
是一个可怕的想法。不要将具有大写差异的语言关键字用作类型名称。
C
是Class
类型的编译时值。它不是一种类型。
typename Cls = C
尝试将类型Class
的值分配给某个类型。这是一个类似于说“拾起悲伤”的错误。伤心不是名词,它不是你能接受的东西。
使代码编译的最简单方法是完全删除onlyLegalForSecondaryEntities
,并删除所有引用。
通常,在标准下,您不能拥有模板方法,该方法仅在某些参数传递给它所在的模板类时才有效。这样做会使您的程序生成错误,无需诊断。
这很接近:
template<Class Cls = C,
std::enable_if_t< Cls == Secondary, int> =0
>
void onlyLegalForSecondaryEntities() {
std::cout << "Works" << std::endl;
}
除了即使在Entity<Primary>
上,您也可以.onlyLegalForSecondaryEntities<Secondary>()
。
如果您不想允许这样做,我会使用CRTP。
template<bool b, class D>
struct empty_if_false {};
template<class D>
struct empty_if_false<true, D> {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D*>(this); }
void onlyLegalForSecondaryEntities() {
// use self() instead of this in this method to get at a this pointer
std::cout << "Works" << std::endl;
}
};
然后:
template<Class C>
class Entity:public empty_if_false< C==Secondary, Entity<C> > {
有条件地拥有该方法。