使用 enable_if 的部分模板专业化

Partial Template Specialization using enable_if

我正在尝试了解如何使用 std::enable_if 的类型特征来“启用”class 的部分特化。这是我试图开始工作的示例代码L

#include <type_traits>
#include <iostream>

class AbstractFoo {
public:
    virtual const char* name() const = 0;
};

template <typename T, typename Enable = void>
class Foo;

template <>
class Foo<int> : public AbstractFoo{
public:
    const char* name() const override { return "int"; }
};

template <>
class Foo<char> : public AbstractFoo {
public:
    const char* name() const override { return "char"; }
};

template <typename T>
class Foo<T, typename std::enable_if<std::is_enum<T>::value, T>::type> : public AbstractFoo {
public:
    const char* name() const override { return "enum"; }
};

enum class MyEnum {
    VAL1,
    VAL2,
    VAL3
};

int main() {
    Foo<int> v1;
    Foo<char> v2;
    Foo<MyEnum> v3;
    
    std::cout << "v1.name()=" << v1.name() << std::endl;
    std::cout << "v2.name()=" << v2.name() << std::endl;
    std::cout << "v3.name()=" << v3.name() << std::endl;

    return 0;
};

我的目标是对某些类型(例如 int 和 char)进行特定的特化,但是,如果类型是枚举,则使用我的部分特化。但是,当我尝试编译此代码时,出现以下错误

error: aggregate 'Foo v3' has incomplete type and cannot be defined

我认为这意味着我的专业没有被选择,因此永远不会被定义。我做错了什么?

Foo 的声明中,第二个模板参数默认为 void。这意味着以下变量:

Foo<MyEnum> v3;

实际上是

Foo<MyEnum, void> v3;

现在的问题是:这符合你想要的专业化吗?不是真的,因为在你的枚举专业化中:

  • std::is_enum<T>::value = trueT = MyEnum
  • std::enable_if<std::is_enum<T>::value, T>::type = T = MyEnumT=MyEnum

因此,对于 T=MyEnum,您给出 Foo<T, T> 的特化,这与上面的变量不匹配。

如评论中所述,一个简单的解决方法是将专业化声明为

class Foo<T, typename std::enable_if<std::is_enum<T>::value>::type>

这样,当T=MyEnum时,第二个模板参数是void,所以匹配v3.

的变量声明