【问题标题】:compile time substitution in initializer list初始化列表中的编译时替换
【发布时间】:2017-10-26 18:10:40
【问题描述】:

我有一个模板类,它确保基本上只使用 2 个枚举中的 1 个进行实例化。现在我想根据实例化的枚举在初始化程序中设置模板参数的值。像这样的:

enum class MyFirstEnum { red, green, orange };
enum class MySecondEnum { blue, yellow, red };

template <class T>
class MyClass
{
    static_assert(
        std::is_same<T, MyFirstEnum>::value || std::is_same<T, MySecondEnum>::value, 
        "Template parameter must be either MyFirstEnum or MySecondEnum"
    );
public:
    MyClass() 
        : value(std::is_same<T, MyFirstEnum>::value ? MyFirstEnum::red : MySecondEnum::blue)
    {
    }
private:
    T value;

}

但是编译器当然会抱怨,因为类型不匹配并且三元不是编译时替换。有没有办法根据类型参数分配正确的值?

感谢任何帮助。我仅限于 c++11

【问题讨论】:

  • value 不可能同时拥有这两种类型的实例(即MyFirstEnumMySecondEnum
  • MyFirstEnum::redMySecondEnum::blue 的值都是 0,所以可能只使用 value(static_cast&lt;T&gt;(0),或者只使用 value() 并让编译器为您对其进行零初始化。
  • @nakiya 当然那为什么初始化列表中有三元来填写正确的类型。提供的代码不会编译,因为这是运行时检查,但它需要是编译时检查。
  • @JohnSmith:三元 ?: 运算符的两个操作数必须是相同的类型。你的不是。
  • @RemyLebeau 提供的代码只是一个示例,我的真实用例没有该保证。

标签: c++ c++11 templates enums constexpr


【解决方案1】:

在您的示例中,MyFirstEnum::redMySecondEnum::blue 的值都为 0,所以试试这个:

MyClass() 
    : value(static_cast<T>(0))
{
}

或者只是:

MyClass() 
    : value(0)
{
}

或者,让编译器为您将值初始化为零:

MyClass() 
    : value()
{
}

另一方面,如果不能保证初始值始终为 0,那么我建议为每个 enum 定义一个 traits 结构并让它们指定所需的默认值:

enum class MyFirstEnum { red, green, orange };
enum class MySecondEnum { blue, yellow, red };

template<typename T>
struct MyClass_traits
{
};

template<>
struct MyClass_traits<MyFirstEnum>
{
    static const MyFirstEnum initial_value = MyFirstEnum::red;
};

template<>
struct MyClass_traits<MySecondEnum>
{
    static const MySecondEnum initial_value = MySecondEnum::yellow;
};

template <class T, typename traits = MyClass_traits<T> >
class MyClass
{
    static_assert(
        !(std::is_same<T, MyFirstEnum>::value || std::is_same<T, MySecondEnum>::value), 
        "Template parameter must be either MyFirstEnum or MySecondEnum"
    );

public:
    MyClass() 
        : value(traits::initial_value)
    {
    }

private:
    T value;
};

【讨论】:

    【解决方案2】:

    基于 Remy 对特质类的推荐。

    enum class MyFirstEnum { red, green, orange };
    enum class MySecondEnum { blue, yellow, red };
    
    template<class T>
    struct Traits
    {
    };
    
    template<>
    struct Traits<MyFirstEnum>
    {
        static MyFirstEnum default_val() {return MyFirstEnum::red;}
    };
    
    template<>
    struct Traits<MySecondEnum>
    {
        static MySecondEnum default_val() {return MySecondEnum::blue;}
    };
    
    template <class T>
    class MyClass
    {
        static_assert(
            !(std::is_same<T, MyFirstEnum>::value || std::is_same<T, MySecondEnum>::value), 
            "Template parameter must be either MyFirstEnum or MySecondEnum"
        );
    public:
        MyClass() 
            : value(Traits<T>::default_val())
        {
        }
    private:
        T value;
    
    }
    

    未测试。

    【讨论】:

      猜你喜欢
      • 2021-08-31
      • 2014-10-06
      • 1970-01-01
      • 2018-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多