我想创建一个对象,std::array<T, N>但问题是我只能使用返回constexpr类型的函数,否则编译器会抱怨。这里的问题是我需要根据另一个数组的大小来计算该数组的长度,可能是这样的:
template <typename T>
struct DataLength
{
template <typename iter>
size_t maxPossibleLength(iter begin, iter end)
{
size_t m_size = 0;
while (begin != end) {
m_size = m_size << 8 | std::numeric_limits<T>::max(); /* 0xff for uchar*/
begin++;
}
return m_size;
}
}
Run Code Online (Sandbox Code Playgroud)
我如何转换这个函数的输出,以便我可以使用它而不是N?
在 C++14 中,由于constexpr不再隐式const,constexpr成员函数可以修改类的数据成员:
struct myclass
{
int member;
constexpr myclass(int input): member(input) {}
constexpr void f() {member = 42;} // Is it allowed?
};
Run Code Online (Sandbox Code Playgroud) 是否可以constexpr在某一点声明一个 const 数组(可能),然后在另一个地方定义它,一次一个元素?
例如
extern constexpr int myArray[100];
myArray[0] = myConstexprFunction(0);
myArray[1] = myConstexprFunction(1);
// ...
myArray[100] = myConstexprFunction(100);
Run Code Online (Sandbox Code Playgroud)
我正在尝试做的将需要这样的东西。也许可以使用以下内容:http : //b.atch.se/posts/constexpr-counter/
但是如果这种技术在下一个 C++ 标准中是非法的(我希望不是),我想使用更安全的技术。
[编辑]放宽一些要求怎么样..假设我想做这样的事情:
constexpr int myConstExprFunction(int arg) { return arg + 100;}
// other code...
constexpr int a = myConstExprFunctionBegin(10);
constexpr int b = myConstExprFunction(20);
constexpr int c = myConstExprFunction(30);
constexpr int d = myConstExprFunctionEnd(40);
Run Code Online (Sandbox Code Playgroud)
我想要的是 myConstExprFunctionEnd 能够使用先前函数创建的值生成最终数组。当然,一切都在编译时。
[EDIT2] C++11 解决方案非常受欢迎
我写了一个简单的例子来解决我在写他的程序时遇到的问题。
\n\n在程序执行期间,当从函数返回值时,我得到 input1 和 input2 的值,这些值永远不会改变。然后稍后,在程序过程中进行各种计算后,我得到一个结果,该结果也不再可变。
\n\n我正在尝试使用 switch-case 来比较它们,但出现一个错误“\xe2\x80\x98input1\xe2\x80\x99 的值在常量表达式中不可用”。
\n\n#include <iostream>\n\nusing namespace std;\n\nchar getChar()\n{\n char c;\n cin >> c;\n return c;\n}\n\nint main()\n{\n // it doesn\'t work\n const char input1 = getChar();\n const char input2 = getChar();\n\n // it it works\n //const char input1 = \'R\';\n //const char input2 = \'X\';\n\n char result = getChar();\n switch(result)\n {\n case input1:\n cout << "input1" << endl;\n break;\n case input2:\n cout << "input2" << endl;\n break;\n }\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n 据我了解,传统的字符数组的功能,如strlen,strstr等全部由C-标准定义,因为constexpr是C ++ 11,他们没有将其声明。
然而,在C ++ 17的std :: char_traits定义像一些同等功能的发现(这基本上是一个constexpr C ++的版本strchr,或复制这似乎提供类似的东西strcpy。
但是没有find找到子字符串的变体,只有一个字符。那么是否有一些 C++ constexpr 相当于strstr标准的一部分?
我试图理解为什么编译器在这里抱怨:
// cexpr_test.cpp
#include <initializer_list>
constexpr int test_cexpr(std::initializer_list<const char*> x)
{
return (int) (*x.begin())[0]; // ensuring the value isn't optimized out.
}
int main()
{
constexpr int r1 = test_cexpr({ "why does this work," });
constexpr std::initializer_list<const char*> broken { "but this doesn't?" };
constexpr int r2 = test_cexpr(broken);
return r1 + r2;
}
Run Code Online (Sandbox Code Playgroud)
编译时产生的消息
g++ -std=c++11 -Wall -Werror cexpr_test.cpp
Run Code Online (Sandbox Code Playgroud)
如下:
cexpr_test.cpp:在函数“int main()”中:cexpr_test.cpp:12:76:错误:“const std::initializer_list{((const char* const*)(&)), 1}”不是常量表达式 12 | constexpr std::initializer_list 损坏 {“但这不是?” }; |
令人困惑的是,为什么它在没有任何问题的情况下构建第一个初始化列表。我在这里缺少什么?
c++ string-literals initializer-list language-lawyer constexpr
如果使用 gcc v10 编译,下面的代码会出现错误,但对于 gcc v9,代码没问题。
template<auto N>
struct A {
constexpr auto size() const {
return N;
}
};
template<typename T>
void foo1(const T& a) {
constexpr auto s = a.size(); // Why error here?
}
template<typename T>
void foo2(T a) {
constexpr auto s = a.size(); // OK
}
int main() {
A<10> x1;
foo1(x1);
foo2(x1);
A<x1.size()> x2; // OK
constexpr auto s = x1.size(); // OK
}
Run Code Online (Sandbox Code Playgroud)
在我的理解中,成员函数 size() 在所有情况下都可以称为 constexpr。但是在一种情况下,与 gcc9 相比,gcc10 的行为发生了变化:如果参数由 const-ref 传递。我不明白为什么这不应该是 constexpr? …
我想确认这段代码是合法的(或不合法的?)C++17。
#include <iostream>
template<int N> inline constexpr float MyConst;
template<> inline constexpr float MyConst<1> = 1.1f;
template<> inline constexpr float MyConst<2> = 2.2f;
int main ()
{
std::cout << MyConst<1> << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果由g++和MSVC编译,我不会得到错误(并得到正确的输出),
但是Intel和clang给出了一个错误:
test.cpp(3): error: missing initializer for constexpr variable
template<int N> inline constexpr float MyConst;
^
Run Code Online (Sandbox Code Playgroud)
用-std=c++17(/std:c++17对于 MSVC)编译。
在 Godbolt 和我的本地机器上尝试了最新的编译器。
在以下代码中,我尝试存储对另一个类的 const 引用:
struct A {
};
struct B {
constexpr B(A const & _a) : a(_a) {}
A const & a;
};
int main() {
constexpr A s1;
constexpr B s2{s1};
}
Run Code Online (Sandbox Code Playgroud)
然而,编译器(gcc 11.1)抱怨:
cctest.cpp: In function ‘int main()’:
cctest.cpp:12:22: error: ‘B{s1}’ is not a constant expression
12 | constexpr B s2{s1};
|
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚为什么s1不被视为常量表达式。s1本身是代码中的 constexpr。我知道这可能与引用的生命周期有关,但我无法弄清楚逻辑。在这个例子的代码中,我不想存储 A 的副本,我真的只想要一个引用或(智能)指针。所以:
s1不是常量表达式?非常感谢!
我的意思是,有可能以某种方式做这样的事情吗?
class Color {
public:
static constexpr Color BLACK = {0, 0, 0};
constexpr Color(int r, int g, int b) : r_(r), g_(g), b_(b) {}
private:
int r_;
int g_;
int b_;
};
Run Code Online (Sandbox Code Playgroud)
编译器Color在定义BLACK常量时抱怨类不完整。