在C++ 11之前,仅当变量声明为const,初始化程序是常量表达式并且是整数或枚举类型时,变量的值才能用于常量表达式.如果使用constexpr关键字定义变量,则 C++ 11 将删除变量必须为整数或枚举类型的限制:
constexpr double earth_gravitational_acceleration = 9.8;
constexpr double moon_gravitational_acceleration = earth_gravitational_acceleration / 6.0;
Run Code Online (Sandbox Code Playgroud)
这是什么意思?特别是,它是否意味着:
const double earth_gravitational_acceleration = 9.8;
const double moon_gravitational_acceleration = earth_gravitational_acceleration / 6.0;
Run Code Online (Sandbox Code Playgroud)
在C++ 11之前的C++中是非法的?G ++与此完全OK,即使有-ansi,-pedantic等...
谢谢!
我正在使用C++ constexpr在编译时评估此代码可以正确评估的计算的Fibonacci序列的最大项.为此,我使用以下代码:
constexpr unsigned long long fibo(unsigned n) {
return (n < 2) ? 1 : fibo(n-1)+fibo(n-2);
}
constexpr unsigned max_fibo(unsigned n) {
return (fibo(n+1) >= fibo(n)) ? max_fibo(n+1) : n;
}
const unsigned MAX_FIBO_TERM = max_fibo(0);
Run Code Online (Sandbox Code Playgroud)
这很好,并快速构造MAX_FIBO_TERM(我的机器上的92)正确的值.但是,使用该fibo函数在运行时实际计算项是非常慢的(仅计算前48个项需要大约90秒).
我可以使用替代函数来计算更快的术语:
unsigned long long fiboiter(unsigned n, unsigned long long &prev,
unsigned long long &prevprev) {
return prev = (n < 2) ? prevprev = 1 :
(std::swap(prev, prevprev), prev + prevprev);
}
Run Code Online (Sandbox Code Playgroud)
但是,我似乎无法将其变为有效的constexpr功能.(这就是为什么它以那种奇怪的方式写的.)当我运行这个版本时,我的机器需要0.005秒.
当我用g++ …
我对这个片段感到困惑:
constexpr int f(bool b) {
return b ? throw 0 : 0; }
constexpr int f() { return f(true); }
Run Code Online (Sandbox Code Playgroud)
直接来自c ++草案.我所强调的一点是,为什么标准将constexpr没有参数的函数定义为格式错误(在同一链接中说明).愿有人澄清吗?
Ben Deane提到了throw技巧,它确保在非constexpr上下文中使用constexpr函数时出现链接错误.
这是我的看法:
#include <iostream>
struct Exc;
constexpr int foo( int a )
{
if( a == 42 )
{
throw Exc{};
}
return 666;
}
int main()
{
constexpr auto ret = foo(43);
std::cout << ret << "\n";
return ret;
}
Run Code Online (Sandbox Code Playgroud)
但我无法使它工作(clang ++ 3.8.1-23和g ++ 6.3.0):
$ clang++ -std=c++14 main.cpp
main.cpp:9:15: error: invalid use of incomplete type 'ExcBase'
throw ExcBase{};
^~~~~~~~~
main.cpp:3:8: note: forward declaration of 'ExcBase'
struct ExcBase;
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
这个帖子中的评论暗示了另一个技巧:
#include <iostream> …Run Code Online (Sandbox Code Playgroud) 我想用make_tuple()在constexpr.它适用于全球范围.但它会为static constexpr类成员生成链接错误.
#include <iostream>
#include <tuple>
using namespace std;
class A
{
public:
static constexpr auto z = make_tuple(5, 3.0);
};
constexpr auto tp = make_tuple(6, 3.2);
int main()
{
cout << get<0>(tp) << " " << get<1>(tp) << endl; // OK
cout << get<0>(A::z) << " " << get<1>(A::z) << endl; // error: (.text+0x5a): undefined reference to `A::z'
// (.text+0x67): undefined reference to `A::z'
}
Run Code Online (Sandbox Code Playgroud)
我已经检查了这里 make_tuple本身不是constexpr在c++11.我猜这不是问题.如果是,它将生成编译错误而不是链接错误. …
请考虑以下代码:
template<int nIndex>
int Fibonacci()
{
if constexpr (nIndex == 0) return 0;
if constexpr (nIndex == 1) return 1;
static_assert(nIndex >= 0, "Invalid index passed to Fibonacci()");
return Fibonacci<nIndex - 1>() + Fibonacci<nIndex - 2>();
}
int main()
{
Fibonacci<3>(); // 2
//Fibonacci<-1>(); // Fires assertion
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我在VS2017中运行它时,编译器输出:
error C2338: Invalid index passed to Fibonacci()
note: see reference to function template instantiation 'int Fibonacci<-1>(void)' being compiled
note: see reference to function template instantiation 'int Fibonacci<1>(void)' being compiled …Run Code Online (Sandbox Code Playgroud) 我有这个代码:
class myClass
{
constexpr int x = 4;
};
Run Code Online (Sandbox Code Playgroud)
在visual studio 2015上,我收到此错误:
'constexpr' is not valid here
Run Code Online (Sandbox Code Playgroud)
为什么我收到此错误?我想要一个const静态变量,我可以在头文件中初始化它.
在下一步中,我想将我的类更改为模板,但此常量与clas的类型无关.
给定两个constexpr功能,是否可以将它们组合为一个功能?
template <char... C>
constexpr int boo()
{
char ch[] = { C... };
int count = 0;
for (char c : ch)
{
if (c != '0') count += 1;
}
return count;
}
template <char... C>
constexpr auto foo()
{
std::array<char, boo<C...>()> x{};
return x;
}
Run Code Online (Sandbox Code Playgroud)
如示例所示,我可以将' count'作为常量返回。我的问题是我不能count在声明的函数中使用' '作为常量。也就是说,如果将' boo()' 的主体放在' foo()'中,则编译器将抛出' count'不是常量。
c++ template-meta-programming variadic-templates constexpr c++17
我已经阅读了std::is_constant_evaluated()定义,但是我仍然不确定为什么(1)无法在最新的GCC上运行:error: 'x' is not a constant expression
template<auto v>
struct s
{};
constexpr void f(int x)
{
if (std::is_constant_evaluated())
{
// constexpr int z=x; (1)
// s<x> a; (2)
}
}
int main(int argc, char* argv[])
{
f(4);
//f(argc);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
随着分支 std::is_constant_evaluated()
更新
我可以将“解释性”信息“传输”到函数中吗?基本上决定f()是否使用constexprx 进行调用。
UPDATE 关于我要实现的目标的一个更复杂的示例:如果可能,此示例应在编译时对参数进行字符串化。
template<auto v>
struct dummy_stringify
{
static constexpr auto str=v==4 ? "4" : "31"; // this is just …Run Code Online (Sandbox Code Playgroud) 我们只是被错字弄糊涂了:“ constexpr bool maxDistance = 10000; ”
gcc和clang都编译此文件而没有任何警告。
真正的错误是该变量不应为bool类型,而应为整数类型。
我们如何确保将来收到编译器警告?
#include <iostream>
constexpr bool number = 1234;
int main(int argc, char* argv[])
{
std::cout << number + 10000 << std::endl; // prints 10001.
return number;
}
Run Code Online (Sandbox Code Playgroud)
这里的错误是变量声明的类型错误,但是clang和gcc均未给出警告。
gcc -Wall -std=c++14 test.cpp -lstdc++
clang -Wall -std=c++14 test.cpp -lstdc++
Run Code Online (Sandbox Code Playgroud)
(使用gcc 5.4.0和clang 3.8.0)
注意:此后,我已经了解了一个可能的编译标志:-Wint-in-bool-context但是,这似乎在我使用的版本(5.4.0)和clang(3.8.0)中均未实现。
这是正确的方法吗?