I have made a constexpr
string type, which I call StaticString
. I got this idea from this website.
我做了一个constexpr字符串类型,我称之为StaticString。我是从这个网站上得到这个想法的。
I am having some weird issues with the compiler treating a variable as a constexpr
on one line, and then not a constexpr
on the next line.
我遇到了一些奇怪的问题,编译器将一个变量作为一个constexpr在一行上处理,而不是在下一行上的constexpr。
Here is the code:
这是代码:
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");
}
And here is the definition of 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;
}
So my question is this: why does world
get treated as a constexpr
on one line but not the next?
所以我的问题是:为什么人们把世界看成是一条线上的,而不是另一条线上的?
NOTE: This is the error I get:
注:这是我得到的错误:
'StaticString{((const char*)"world"), 5ull, ((const prototypeInd::util::StaticString*)(&<anonymous>))}' is not a constant expression
Also I am using gcc
我也在使用gcc
1 个解决方案
#1
7
Discussion
Your world
variable is constexpr
but operator+
in expression:
你的世界变量是constexpr但运算符+的表达式:
constexpr StaticString both3 = "hello " + world;
although marked as constexpr
is not. Because in its return statement:
虽然标记为constexpr不是。因为在返回语句中:
return StaticString(str) + other;
due to the creation of the temporary StaticString(str)
pointers to non-static-storage duration temporaries are also being created. This is attributed to the fact that in your StaticString
objects you're storing addresses of non-static-storage duration temporaries and these kind of pointers are not allowed in constant expressions.
由于创建了指向非静态存储时间的临时静态字符串(str)指针,因此也创建了临时指针。这是由于在静态字符串对象中,您正在存储非静态存储持续时间的地址,而这些指针在常量表达式中是不允许的。
Justification
According to the standard §5.20/p5 Constant expressions [expr.const] (Emphasis Mine):
根据标准§5.20 / p5常数表达式[expr。const](强调我的):
A constant expression is either a glvalue core constant expression whose value refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
常数表达式是一个glvalue核心常量表达式,其值是指一个常数表达式(定义如下)的允许结果的实体,或一个prvalue核心常量表达式,其值满足以下约束:
(5.1) — if the value is an object of class type, each non-static data member of reference type refers to an entity that is a permitted result of a constant expression,
(5.1) -如果该值是类类型的对象,则引用类型的每个非静态数据成员都指一个实体,该实体是常量表达式的允许结果,
(5.2) — if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object (5.7), the address of a function, or a null pointer value, and
(5.2) -如果值为指针类型,则它包含具有静态存储持续时间的对象的地址、该对象结束后的地址(5.7)、函数的地址或空指针值,以及
(5.3) — if the value is an object of class or array type, each subobject satisfies these constraints for the value.
(5.3) -如果该值是类或数组类型的对象,则每个子对象都满足该值的这些约束。
An entity is a permitted result of a constant expression if it is an object with static storage duration that is either not a temporary object or is a temporary object whose value satisfies the above constraints, or it is a function.
如果实体不是一个临时对象,或者是一个值满足上述约束的临时对象,或者是一个函数,那么它就是一个常量表达式的允许结果。
.
。
#1
7
Discussion
Your world
variable is constexpr
but operator+
in expression:
你的世界变量是constexpr但运算符+的表达式:
constexpr StaticString both3 = "hello " + world;
although marked as constexpr
is not. Because in its return statement:
虽然标记为constexpr不是。因为在返回语句中:
return StaticString(str) + other;
due to the creation of the temporary StaticString(str)
pointers to non-static-storage duration temporaries are also being created. This is attributed to the fact that in your StaticString
objects you're storing addresses of non-static-storage duration temporaries and these kind of pointers are not allowed in constant expressions.
由于创建了指向非静态存储时间的临时静态字符串(str)指针,因此也创建了临时指针。这是由于在静态字符串对象中,您正在存储非静态存储持续时间的地址,而这些指针在常量表达式中是不允许的。
Justification
According to the standard §5.20/p5 Constant expressions [expr.const] (Emphasis Mine):
根据标准§5.20 / p5常数表达式[expr。const](强调我的):
A constant expression is either a glvalue core constant expression whose value refers to an entity that is a permitted result of a constant expression (as defined below), or a prvalue core constant expression whose value satisfies the following constraints:
常数表达式是一个glvalue核心常量表达式,其值是指一个常数表达式(定义如下)的允许结果的实体,或一个prvalue核心常量表达式,其值满足以下约束:
(5.1) — if the value is an object of class type, each non-static data member of reference type refers to an entity that is a permitted result of a constant expression,
(5.1) -如果该值是类类型的对象,则引用类型的每个非静态数据成员都指一个实体,该实体是常量表达式的允许结果,
(5.2) — if the value is of pointer type, it contains the address of an object with static storage duration, the address past the end of such an object (5.7), the address of a function, or a null pointer value, and
(5.2) -如果值为指针类型,则它包含具有静态存储持续时间的对象的地址、该对象结束后的地址(5.7)、函数的地址或空指针值,以及
(5.3) — if the value is an object of class or array type, each subobject satisfies these constraints for the value.
(5.3) -如果该值是类或数组类型的对象,则每个子对象都满足该值的这些约束。
An entity is a permitted result of a constant expression if it is an object with static storage duration that is either not a temporary object or is a temporary object whose value satisfies the above constraints, or it is a function.
如果实体不是一个临时对象,或者是一个值满足上述约束的临时对象,或者是一个函数,那么它就是一个常量表达式的允许结果。
.
。