使用enable_if进行部分模板专业化

发布于 2025-01-10 02:43:45 字数 1322 浏览 2 评论 0 原文

我试图了解如何使用 std::enable_if 的类型特征来“启用”类的部分专业化。这是我试图运行的示例代码。

#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)进行特定的专业化,但是,如果类型是枚举,则使用我的部分专业化。但是,当我尝试编译此代码时,出现以下错误

错误:聚合“Foo v3”的类型不完整,无法 定义

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

I am trying to understand how to use type traits with std::enable_if to "enable" partial specializations of a class. Here is the example code I am attempting to get workingL

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

My goal is to have specific specializations for certain types (e.g., int and char), but, if the type is an enum, to use my partial specialization. However, when I attempt to compile this code, I get the following error

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

Which I assume means my specialization was not chosen and thus never becomes defined. What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

十雾 2025-01-17 02:43:45

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

Foo<MyEnum> v3;

实际上是

Foo<MyEnum, void> v3;

现在的问题是:这是否对应于您想要的专业化?不是真的,因为在您对枚举的专门化中:

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

因此,对于 T=MyEnum,您给出 Foo 的专业化,它与变量不匹配多于。

正如评论中所述,一个简单的解决方法是将特化声明为这样

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

,当 T=MyEnum 时,第二个模板参数为 void,因此它与变量声明匹配v3

In the declaration of Foo the second template parameter defaults to void. That means that the following variable:

Foo<MyEnum> v3;

is actually

Foo<MyEnum, void> v3;

Now the question is: does this correspond to the specialization you want? Not really, because in your specialization for enum:

  • std::is_enum<T>::value = true when T = MyEnum
  • std::enable_if<std::is_enum<T>::value, T>::type = T = MyEnum
    when T=MyEnum

So, for T=MyEnum, your give the specialization for Foo<T, T>, which does not match the variable above.

As noted in a comment, a simple fix is to declare the specialization as

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

In this way, the second template parameter is void when T=MyEnum, so it matches the variable declaration of v3.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文