为什么constexpr成员函数仅在泛型类中返回自定义类型时才有效?

时间:2017-09-14 09:52:31

标签: c++ c++14 c++17 constexpr

这是一个错误还是故意的(使用VS2017更新15.3.4)?

以下内容无法编译,因为CustomType是非文字。

class A
{
public:
    // ... some constructors
    inline constexpr auto Value() const { return _value; }
private:
    const CustomType _value;
}

但这完全没问题:

template< //... some templates
    >
class A
{
public:
    // ... some constructors
    inline constexpr auto Value() const { return _value; }
private:
    const CustomType _value;
}

为什么!?如果没有使用constexpr,我是否会在第一时间错过任何好处?我在第二个实例中使用constexpr获得了什么好处,或者编译器只是懒惰而完全忽略了错误?或者这一切都是故意这样做的,因为我不知道泛型类和非泛型类之间存在某些差异。

目前,我只能假设这是故意的,因为它使用模板参数提供元编程功能,这在我目前的情况下根本不需要。那么为什么不能首先在constexpr中返回非文字类型呢?我知道这个帖子中有很多问题,但也许只有一个答案就足够了。

为清楚起见,请运行以下命令:

class CustomType
{
public:
    inline CustomType(const int& val)
        : _value(val) {}

    inline constexpr auto Value() const { return _value; }

private:
    int _value;
};

template<int N>
class A
{
public:
    inline constexpr A(const CustomType& Val)
        : _value(Val) {}
    inline ~A() {}

    inline constexpr A(const A& rhs)
        : _value(rhs._value) {}
    inline constexpr const A& operator=(const A& rhs) const { return rhs; }

    inline constexpr auto Value() const { return _value; }
private:
    const CustomType _value;
};

如果删除template<int N>,代码将不再编译。

2 个答案:

答案 0 :(得分:4)

从最新的标准草案[dcl.constexpr]/6(我的重点):

  

如果constexpr函数模板的实例化模板特化或类模板的成员函数无法满足constexpr函数或constexpr构造函数的要求,那么该特化仍然是constexpr函数或constexpr构造函数,即使调用这样的函数不能出现在常量表达式中。 如果在被视为非模板函数或构造函数时模板的特化不满足constexpr函数或constexpr构造函数的要求,则模板格式错误,无需诊断。

您的函数显然无法满足constexpr函数的要求,因为它的返回类型不是文字类型。这与上面引用的条款相结合,会让您相信您的代码实际上是格式错误的,无需诊断(这几乎就是发生的事情)。不过,我希望constexpr使用成员函数来导致诊断。

另请参阅the accepted answer问题 Why do templates allow constexpr function members with non-constexpr constructors? ,该问题处理完全相同的情况,但函数恰好是自由函数而不是成员函数。< / p>

答案 1 :(得分:0)

模板类中的方法在实际使用之前并未实际实例化。也许编译器会检查它的语法健全性,但绝不会检查语义。