为什么这个 std::enable_if 不起作用

Why does this std::enable_if not work

从这个问题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

如何编译此代码?

您将 Class 用于 enum 是一个糟糕的主意。不要使用大小写不同的语言关键字作为类型名称。

CClass 类型的编译时值。不是类型。

typename Cls = C 尝试将类型 Class 的值分配给一个类型。这是类似于说 "picking up a sad" 的错误。 sad 不是名词,不是随便捡的。

使代码编译通过的最简单方法是完全删除 onlyLegalForSecondaryEntities 以及对它的所有引用。

一般来说,根据标准,您不能拥有仅在某些参数传递给模板时有效的模板方法 class 它存在于其中。这样做会使您的程序格式错误,不需要诊断。

这很接近:

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> > {

有条件有方法