C++ 11编译器(以及他们)是否注意到一个函数是constexpr并且即使它们未被声明为constexpr也会将它们视为这样?
我正在使用维基百科中的示例向使用constexpr的人展示:
int get_five() {return 5;}
int some_value[get_five() + 7]; // Create an array of 12 integers. Ill-formed C++
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是编译器没问题.所以,我进一步更改了get_five()以获取一些int参数,将它们相乘并返回结果,同时仍未明确声明为constexpr.编译器也可以.似乎如果编译器可以做到这一点,那么为了明确声明constexpr的某些东西,没有太多的意义.
我以下列方式宣布了一堂课
class A
{
struct B
{
constexpr
B(uint8_t _a, uint8_t _b) :
a(_a),
b(_b)
{}
bool operator==(const B& rhs) const
{
if((a == rhs.a)&&
(b == rhs.b))
{
return true;
}
return false;
}
uint8_t a;
uint8_t b;
};
constexpr static B b {B(0x00, 0x00)};
};
Run Code Online (Sandbox Code Playgroud)
但是g ++说
错误:字段初始值设定项不是常量
无法弄清楚我错在哪里.
将不胜感激任何帮助!
谢谢和reagards!
我正在尝试在编译时静态实例化一些对象.我需要的是设置成员int变量增量值.例如,我创建的第一个对象将具有0值,第二个1,第三个2 ...总结我需要这样的东西,但它必须作为constexpr工作.
//header
class MyClass final {
private:
static int IDcount;
public:
const int ID;
constexpr MyClass(args);
//~MyClass();
};
//source
int MyClass::IDcount = 0;
constexpr MyClass::MyClass(args) : ID(MyClass::IDcount++) {
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在编译时实现这一点(不将ID作为构造函数的参数)
我有以下代码:
main.cpp中
#include <cstdint>
#include <type_traits>
enum class FooEnum : uint8_t{
Foo1 = 0,
Foo2 = 1
};
constexpr uint32_t& operator|= (uint32_t& lhs, FooEnum rhs) {
return lhs |= 1u << static_cast<uint8_t>(rhs);
}
int main() {
uint32_t bar{0};
bar|=FooEnum::Foo1;
}
Run Code Online (Sandbox Code Playgroud)
基本上,|=运算符应该采用枚举并设置位,其位置对应于其整数值.
在fedora 21上用clang ++ 3.5.0编译时,一切正常,但是当用g ++ 4.9.2编译时,它会抛出一个错误,说这不是一个常量表达式:
main.cpp: In function ‘constexpr uint32_t& operator|=(uint32_t&, FooEnum)’:
main.cpp:16:2: error: expression ‘(lhs = (lhs | (1u << ((int)rhs))))’ is not a constant-expression
}
^
Run Code Online (Sandbox Code Playgroud)
对于所有类型的编译器标志组合都是如此,但是你可以测试它g++ -std=c++11 -o …
例:
int main(int argc, char**)
{
constexpr int a = argc * 0;
(void)a;
constexpr int b = argc - argc;
(void)b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
argc不是常量表达式,但编译器仍能够在两种情况下计算结果a和b编译时间(即0).
标准是否允许编译器与g ++一样聪明constexpr?
在标准论文P0092R1中,Howard Hinnant写道:
template <class To, class Rep, class Period,
class = enable_if_t<detail::is_duration<To>{}>>
constexpr
To floor(const duration<Rep, Period>& d)
{
To t = duration_cast<To>(d);
if (t > d)
--t;
return t;
}
Run Code Online (Sandbox Code Playgroud)
这段代码怎么样?问题是,operator--a std::chrono::duration不是constexpr操作.它被定义为:
duration& operator--();
Run Code Online (Sandbox Code Playgroud)
然而,这段代码编译,并在编译时给出正确的答案:
static_assert(floor<hours>(minutes{3}).count() == 0, "”);
Run Code Online (Sandbox Code Playgroud)
那是怎么回事?
cppreference指出:
在对象声明或非静态成员函数中使用的constexpr说明符(直到C++ 14)暗示const.
"对象声明"是否意味着"任何变量声明"?
即
constexpr const int someConstant = 3;
Run Code Online (Sandbox Code Playgroud)
相当于
constexpr int someConstant = 3;
Run Code Online (Sandbox Code Playgroud)
在C++ 11,C++ 14和C++ 17中?
考虑以下两个程序:
#include<variant>
#include<iostream>
constexpr auto f() {
using T = std::variant<bool, int>;
T t(false);
t = T(true);
return std::get<bool>(t);
}
template<auto V>
void print() { std::cout << V << "\n"; }
int main() {
print<f()>();
}
Run Code Online (Sandbox Code Playgroud)
和
#include<variant>
#include<iostream>
constexpr auto f() {
using T = std::variant<bool, int>;
T t(false);
t = T(42);
return std::get<int>(t);
}
template<auto V>
void print() { std::cout << V << "\n"; }
int main() {
print<f()>();
}
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会汇编这两项并输出预期结果.在两种情况下,Clang都不会使用以下错误消息编译它们中的任何一个:
<source>:4:16: error: constexpr function never produces a …Run Code Online (Sandbox Code Playgroud) 我有以下第三方API:
using StatisticsFunc = double (*)(const std::vector<double> &)
libraryClass::ComputeStatistics(StatisticsFunc sf);
Run Code Online (Sandbox Code Playgroud)
我正在使用这样的:
obj1->ComputeStatistics([](const auto& v) {return histogram("obj1", v);};
obj2->ComputeStatistics([](const auto& v) {return histogram("obj2", v);};
Run Code Online (Sandbox Code Playgroud)
但所有这些lambdas只是重复代码.我宁愿这样:
obj1->ComputeStatistics(getHistogramLambda("obj1"));
Run Code Online (Sandbox Code Playgroud)
所以我需要定义:
constexpr auto getHistogramLambda(const char* name) {
return [](const auto& v) {return histogram(name, v);};
}
Run Code Online (Sandbox Code Playgroud)
但它不起作用,因为name没有被捕获.这也不会起作用:
constexpr auto getHistogramLambda(const char* name) {
return [name](const auto& v) {return histogram(name, v);};
}
Run Code Online (Sandbox Code Playgroud)
因为捕获lambda不再是无状态的,不能转换为函数指针.
Ofc可以将其作为宏来实现,但我想要一个现代的C++ 17解决方案.
传递字符串作为模板参数似乎也是一个选项:https:
//stackoverflow.com/a/28209546/7432927,但我很好奇是否有constexpr办法做到这一点.
考虑以下代码:
#include <cstdint>
static int x = 0;
const uintptr_t arithmetic()
{
static constexpr uintptr_t result = ((uintptr_t)&x) + 1u;
return result;
}
const uintptr_t bitwise()
{
static constexpr uintptr_t result = ((uintptr_t)&x) | 1u;
return result;
}
Run Code Online (Sandbox Code Playgroud)
GCC(所有版本4-9)都arithmetic()可以正常编译,但可以拒绝bitwise():
<source>: In function 'const uintptr_t bitwise()':
<source>:13:57: error: '(((uintptr_t)(& x)) | 1)' is not a constant expression
13 | static constexpr uintptr_t result = ((uintptr_t)&x) | 1u;
| ~~~~~~~~~~~~~~~~^~~~
Run Code Online (Sandbox Code Playgroud)
为什么?请注意,在其他constexpr用例中,按位-或工作正常,但不是这种情况。