【问题标题】:Design of constexpr classes : merging constexpr and non-constexpr versions?constexpr 类的设计:合并 constexpr 和非 constexpr 版本?
【发布时间】:2013-01-01 16:28:53
【问题描述】:

考虑一个只在运行时包装一个值的类:

template <typename Type>
class NonConstValue 
{
    public:
        NonConstValue(const Type& val) : _value(val) {;}
        Type get() const {return _value;}
        void set(const Type& val) const {_value = val;}
    protected:
        Type _value;
};

以及它的 constexpr 版本:

template <typename Type>
class ConstValue 
{
    public:
        constexpr ConstValue(const Type& val) : _value(val) {;}
        constexpr Type get() const {return _value;}
    protected:
        const Type _value;
};

问题 1:您能确认 constexpr 版本的设计方式正确吗?

问题 2:如何将两个类混合成一个名为 Value 的类,该类可以由 constexpr 构造或运行时构造,并且其值可以在运行时或编译时为 get()

编辑: 问题 3:如果 get() 定义在 .cpp 文件中,并且如果我希望 get() 不是 constexpr 内联,那么函数的正确声明是什么?是吗

constexpr inline Type get();

inline constexpr Type get()

还是别的什么?

【问题讨论】:

  • constexpr 函数可以在编译时或运行时调用。
  • 我认为非静态 constexpr 成员函数存在缺陷,因为它们总是暗示 const 函数限定符,即 constexpr foo bar();constexpr foo bar() const; 声明相同。对非成员没有这样的要求,即constexpr foo bar(T&amp;);constexpr foo bar(T&amp;&amp;); 可以都接受非const T(并且可以有涉及非const 限定类类型的常量表达式)。所以要小心。

标签: c++ c++11 constructor constants constexpr


【解决方案1】:

只需将constexpr 说明符添加到每个潜在的常量表达式函数。

template <typename Type>
class Value 
{
public:
    constexpr Value(Type const& val) : _value(val) {}
    constexpr Type const& get() const {return _value;}
    void set(Type const& val) {_value = val;}
protected:
    Type _value;
};

您不需要 constnon-const 版本,因为这可以通过使用 constValue 来完成/em> 或 非常量 类型。

你不需要constexprnon-constexpr版本,constexpr表示潜在的常量表达式和表达式是否结束up 是否是一个常量表达式 取决于它的参数。表达式是否最终在编译时被评估取决于上下文和实现。

【讨论】:

  • +1,正是我要说的。甚至mutable 也允许在constexpr 对象中。
  • 真的很挑剔,但constexpr 是说明符,而不是声明符。
  • @aschepler:谢谢,我知道这不是修饰语,但我错过了正确的术语。
  • @Vincent:添加inline 不会影响函数是否内联。如果它在不同的 .cpp 中,那么它可能不会,因为编译器无法从这样的 .cpp 外部看到它的定义
  • +1 表示正确答案。注意:不必将get() 声明为constexprconst。前者隐含后者。
【解决方案2】:

您的constexpr 类设计正确,只是您输入了错误的构造函数名称(应该是ConstValue,而不是Value)。但我确定这只是一个错字。

constexpr 版本的实例既可以用作编译时对象,也可以用作运行时对象。

template <typename Type>
class ConstValue
{
    public:
        constexpr ConstValue(const Type& val) : _value(val) {;}
        constexpr Type get() const {return _value;}
    protected:
        const Type _value;
};

int main(int argc, char* argv[])
{
    int x[ConstValue<int>(3).get()];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-27
    • 2020-02-19
    • 2018-07-10
    • 1970-01-01
    • 2015-05-04
    • 2023-03-15
    • 2016-07-24
    • 1970-01-01
    相关资源
    最近更新 更多