变量如何既可以是constexpr而不是constexpr?

时间:2016-05-28 22:34:52

标签: c++ constexpr compile-time-constant

我创建了一个constexpr字符串类型,我称之为StaticString。我从this网站获得了这个想法。

我遇到一些奇怪的问题,编译器在一行上将变量视为constexpr,然后在下一行不是constexpr

以下是代码:

constexpr StaticString hello = "hello";
constexpr StaticString hello2 = hello + " ";
constexpr StaticString world = "world";
constexpr StaticString both = hello + " world";
constexpr StaticString both2 = hello2 + world;
//This works fine (world is constexpr?)

//constexpr StaticString both3 = "hello " + world; 
//ERROR: "world" is not constexpr

int main(void)
{
    static_assert(hello[4] == 'o' ,"ERROR");
    static_assert(hello == "hello", "ERROR");
    static_assert(both2 == "hello world", "ERROR");
}

以下是StaticString

的定义
class StaticString{
        const char* const str;
        const size_t len;
        const StaticString* head;
    public:
        template<size_t N>
        constexpr StaticString(const char(&aStr)[N]) 
            : str(aStr), len(N-1), head(nullptr)  //Chop off the null terminating char
        {
            static_assert(N>=1,"String cannot have a negative length");
        }
        template<size_t N>
        constexpr StaticString(const char(&aStr)[N] ,const StaticString* ss) : head(ss), str(aStr),len(N-1) { }
        constexpr StaticString(const char* const aStr ,const size_t len,const StaticString* ss = nullptr) 
            : str(aStr), len(len), head(ss)
        {
        }
        constexpr char GetFromHead(size_t index) const{
            return index < head->GetSize() ? (*head)[index] : str[index - head->GetSize()];
        }
        constexpr char operator[](size_t index) const{
            return head ? GetFromHead(index) : str[index];
        }
        constexpr size_t GetSize() const{
            return head ? len + head->GetSize() : len;
        }
        constexpr bool Equals(const char* const other,size_t len,size_t index = 0) const{

            return (other[0] == (*this)[index]) ? (len > 1 ? Equals(&other[1],len-1,index+1) : true) : false;
        }
        template<size_t N>
        constexpr bool operator==(const char(&other)[N]) const{
            return Equals(other,N-1);
        }
        template<size_t N>
        constexpr StaticString operator+(const char(&other)[N]) const{
            return StaticString(other,this);
        }
        constexpr StaticString operator+(StaticString other) const{
            return StaticString(other.str,other.len,this);
        }

};
template<size_t N>
constexpr StaticString operator+(const char(&str)[N],const StaticString& other){
    return StaticString(str) + other;
}

所以我的问题是这样的:为什么world在一行上被视为constexpr而在下一行却不被视为?{/ p>

注意: 这是我得到的错误:

'StaticString{((const char*)"world"), 5ull, ((const prototypeInd::util::StaticString*)(&<anonymous>))}' is not a constant expression

我也在使用gcc

1 个答案:

答案 0 :(得分:7)

讨论

您的world变量为constexpr,但operator+位于表达式中:

constexpr StaticString both3 = "hello " + world;

虽然标记为constexpr不是。因为在其退货声明中:

return StaticString(str) + other;

由于创建了临时StaticString(str)指向非静态存储持续时间的指针,临时工具也正在创建。这归因于在StaticString对象中存储非静态存储持续时间临时值的地址,并且常量表达式中不允许使用这些类型的指针。

理由

根据标准§5.20/ p5常量表达式[expr.const] Emphasis Mine ):

  

常量表达式是glvalue核心常量表达式   其值是指一个允许的结果的实体   常量表达式(如下定义)或prvalue核心常量   表达式的值满足以下约束:

     

(5.1) - 如果值是类类型的对象,则每个非静态数据   引用类型的成员是指允许的实体   常量表达的结果,

     

(5.2) - 如果值是指针类型,则它包含一个地址   具有静态存储持续时间的对象,该地址过去结束   对象(5.7),函数的地址或空指针值,   和

     

(5.3) - 如果值是类或数组类型的对象,则   子对象满足这些值的约束。

     

如果是实体,则实体是常量表达式的允许结果   具有静态存储持续时间的对象,它不是临时的   object或是一个临时对象,其值满足上述要求   约束,或者它是一种功能。