一个类不能有自己的静态constexpr成员实例吗?

nya*_*108 41 c++ static-members c++11

这段代码给了我不完整的类型错误.问题是什么?一个类不允许拥有自己的静态成员实例吗?有没有办法达到同样的效果?

struct Size
{
    const unsigned int width;
    const unsigned int height;

    static constexpr Size big = { 480, 240 };

    static constexpr Size small = { 210, 170 };

private:

    Size( ) = default;
};
Run Code Online (Sandbox Code Playgroud)

Bri*_*ian 60

一类允许具有相同类型的静态成员.但是,在定义结束之前,类是不完整的,并且不能使用不完整类型定义对象.您可以声明具有不完整类型的对象,并在稍后完成的位置(在类之外)定义它.

struct Size
{
    const unsigned int width;
    const unsigned int height;

    static const Size big;
    static const Size small;

private:

    Size( ) = default;
};

const Size Size::big = { 480, 240 };
const Size Size::small = { 210, 170 };
Run Code Online (Sandbox Code Playgroud)

在这里看到:http://coliru.stacked-crooked.com/a/f43395e5d08a3952

但是,这对constexpr成员不起作用.

  • @ nyarlathotep108它不起作用,因为`static constexpr`成员需要内联初始化. (8认同)

Mik*_*han 39

有没有办法达到同样的效果?

所谓"相同的结果",你特别想要的constexpr的-ness Size::bigSize::small?在这种情况下,这可能足够接近:

struct Size
{
    const unsigned int width = 0;
    const unsigned int height = 0;

    static constexpr Size big() {
        return Size { 480, 240 };
    }

    static constexpr Size small() {
        return Size { 210, 170 };
    }

private:

    constexpr Size() = default;
    constexpr Size(int w, int h )
    : width(w),height(h){}
};

static_assert(Size::big().width == 480,"");
static_assert(Size::small().height == 170,"");
Run Code Online (Sandbox Code Playgroud)


ben*_*enb 6

作为一种解决方法,您可以使用单独的基类,在派生类中定义常量时,该基类的定义是完整的。

struct size_impl
{
//data members and functions here
    unsigned int width;
    unsigned int height;
};


struct size:  public size_impl
{
//create the constants as instantiations of size_impl
    static constexpr size_impl big{480,240};
    static constexpr size_impl small{210,170};

//provide implicit conversion constructor and assignment operator
    constexpr size(const size_impl& s):size_impl(s){}
    using size_impl::operator=;

//put all other constructors here
};

//test:
constexpr size a = size::big;
Run Code Online (Sandbox Code Playgroud)

如果需要,您可以将基类放在单独的命名空间中以隐藏其定义。

代码用 clang 和 gcc 编译