constexpr:constexpr成员的定义和声明 [英] constexpr: definition and declaration for constexpr members

查看:435
本文介绍了constexpr:constexpr成员的定义和声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我想使用诸如make_array之类的便利工具,我将没有机会先声明我的数组,之后再进行更早"的定义,因为我的var的类型在定义之前不可用.

所以我找到了这个答案:
对静态constexpr char []的未定义引用

在下面的示例中,我编写了使用gcc可以正常编译的解决方案,但我不确定这是否是有效的c ++代码,因为它或多或少是带有定义的声明,后来是没有任何内容的定义.可以吗? (编译良好不能保证该代码是有效的c ++)

#include <experimental/array>
#include <iostream>

class Foo
{
    private:
    static decltype(auto) constexpr Bar =
        std::experimental::make_array(
            std::experimental::make_array( 1,2,3 ),
            std::experimental::make_array( 4,5,6 )
            );

    public:
    using ARR_TYPE = decltype( Bar );

    static auto& GetArr( int idx )
    {
        // range check ...
        return Bar[idx];
    }
};

constexpr Foo::ARR_TYPE Foo::Bar;

int main()
{
    for ( auto el: Foo::GetArr(0))
    {
        std::cout << el << std::endl;
    }
 }

控制static constexpr成员的规则在C ++ 1z中有所变化,这很烦人.

Pre C ++ 1z

来自 [class.static.data]

[...]可以使用constexpr说明符在类定义中声明文字类型的静态数据成员;如果是这样,则其声明应指定一个括号等于相等的初始化程序,其中作为赋值表达式的每个初始化程序子句都是一个常量表达式. [...] 如果程序中使用了成员,则该成员仍应在命名空间范围中定义([basic.def.odr]),并且命名空间范围定义不应包含初始化程序

这意味着需要在声明中提供初始值设定项,还需要在名称空间范围提供没有初始值设定项的定义.

您的代码正是这样做的.

发布C ++ 1z

在同一段落中 [class.static.data]

[...]如果使用constexpr说明符声明了该成员,则可以在没有初始化程序的命名空间范围内重新声明该成员(不建议使用此用法;请参见[depr.static_constexpr]). [...]

[depr.static_constexpr]

为了与以前的C ++国际标准兼容,可以在没有初始化程序的类外部冗余地声明constexpr静态数据成员.不建议使用此用法.

因此,这仍然是合法的,但已弃用.

应注意static,但如果constexpr成员(包括static const成员)被odr-used使用,则仍不需要在命名空间范围内具有定义.

If I want to use some convenience stuff like make_array I have no chance to declare my array first and later make the definition as done in "earlier" times because the type of my var is not available before definition.

So I found this answer:
Undefined reference to static constexpr char[]

In the following example I wrote this solution which compiles fine with gcc and I am not sure that this is really valid c++ code, because it is more or less a declaration with definition and later a definition without any content. Is this allowed? ( Compiles fine is not a guarantee that the code is valid c++ )

#include <experimental/array>
#include <iostream>

class Foo
{
    private:
    static decltype(auto) constexpr Bar =
        std::experimental::make_array(
            std::experimental::make_array( 1,2,3 ),
            std::experimental::make_array( 4,5,6 )
            );

    public:
    using ARR_TYPE = decltype( Bar );

    static auto& GetArr( int idx )
    {
        // range check ...
        return Bar[idx];
    }
};

constexpr Foo::ARR_TYPE Foo::Bar;

int main()
{
    for ( auto el: Foo::GetArr(0))
    {
        std::cout << el << std::endl;
    }
 }

解决方案

The rules governing static constexpr members changes in C++1z, which is kinda annoying.

Pre C++1z

From [class.static.data]

[...] A static data member of literal type can be declared in the class definition with the constexpr specifier; if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression. [...] The member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer.

Which means you are required to provide a initializer in the declaration, but also to provide a definition at namespace scope without an initializer.

Your code does exactly that.

Post C++1z

From the same paragraph [class.static.data]

[...] If the member is declared with the constexpr specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see [depr.static_constexpr]). [...]

And from [depr.static_constexpr]

For compatibility with prior C++ International Standards, a constexpr static data member may be redundantly redeclared outside the class with no initializer. This usage is deprecated.

So, this is still legal, but deprecated.

It should be noted static but not constexpr members (including static const members) are still required to have a definition in namespace scope if it is odr-used.

这篇关于constexpr:constexpr成员的定义和声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆