如何使用static_assert与成员initilizer列表一起使用

时间:2015-11-26 04:12:25

标签: c++ c++11 enums c++14 static-assert

我想使用static_assert来强制我的类配置的各种限制。之前我只想使用一个枚举,只允许一个构造函数需要枚举来强制限制我的类。如果我有类似下面的内容并且范围是从0到4,这可以正常工作,但是一旦我有0到500的范围,那么使用枚举变得笨拙。

Some_Class.h

class Some_Class {
    public:
        Some_Class(const unsigned int param);
    private:
        const unsigned int member_param;
};

Some_Class.cpp

Some_Class::Some_Class(const unsigned int param) : member_param(param) {
    static_assert(member_param < 500, "Param must be less than 500.");
};

Main.cpp的

Some_Class foo4(125); // OK
Some_Class foo5(500); // Should fail at compile time.

这是GCC在使用C ++ 14进行编译时抛出的内容:

1>  Some_Class.cpp: In constructor 'Some_Class::Some_Class(unsigned int)':
1>C:\some_path\Some_Class.cpp(3,2): error : non-constant condition for static assertion
1>    static_assert(member_param < 500, "Param must be less than 500.");
1>    ^
1>C:\some_path\Some_Class.cpp(3,2): error : use of 'this' in a constant expression

2 个答案:

答案 0 :(得分:2)

参数值不能用于constexpr。

你必须以某种方式输入编译时间值:

  • 模板全班:

    template<unsigned int size>
    class Some_Class {
        static_assert(size < 500, "Size should be less than 500");
    public:
        constexpr unsigned int member_param = size;
    };
    
  • 传递一个integral_constant:

    template <unsigned int N>
    using uint_c = std::integral_constant<unsigned int, N>;
    
    class Some_Class {
    public:
        template<unsigned int size>
        Some_Class(uint_c<size>) : member_param(size)
        {
            static_assert(size < 500, "Size should be less than 500");
        }
    private:
        unsigned int member_param;
    };
    

答案 1 :(得分:1)

如果您想要编译时检查,您应该使用模板:

template<int size>
class Some_Class {
public:
    Some_Class() : member_param(size) { static_assert(size < 500, "Size should be less than 500"); }
private:
    const unsigned int member_param;
}

然后使用该类,用户必须明确指定大小:

void myFunction() {
    Some_Class<20> class20; // Works
    Some_Class<500> class500; // Compiler error
}

编辑:基于来自@NeilKirk的评论,以下代码将实现相同而不必将整个类作为模板:

class Some_Class {
public:
    template<int size>
    static Some_Class* createClass() {
        static_assert(size < 500, "Size should be less than 500");
        return new Some_Class(size);
    }
private:
    Some_Class(int size) : member_param(size) { assert(size < 500); }
private:
    const unsigned int member_param;
};

它的作用:构造函数接受大小但是是私有的。因此,必须使用作为模板的createClass静态函数创建类,并且可以对大小执行static_assert。

创建对象:

Some_Class* class = Some_Class::createClass<20>();

如果有人从类派生并使构造函数公开,则在构造函数中添加正常断言以供例如。