作为在讨论这个SO问题时提出的一个问题:
申报对象是否合法,可能是N3471constexpr std::initializer_list?例:
constexpr std::initializer_list<int> my_list{};
Run Code Online (Sandbox Code Playgroud)
为什么我认为它可能不合法:initializer_list必须是字面类型; 但有没有保证它是文字类型?
来自N3485的引文.
[dcl.constexpr]/9:
对象声明中使用的constexpr说明符将对象声明为const.这样的对象应具有文字类型并应初始化.
文字类型要求,[basic.types]/10,子项目类类型:
- 具有以下所有属性的类类型(第9节):
- 它有一个简单的析构函数,
- 非静态数据成员(如果有)的brace-or-equal-initializers中的每个构造函数调用和完全表达式都是一个常量表达式(5.19),
- 它是一个聚合类型(8.5.1)或者至少有一个constexpr构造函数或构造函数模板,它不是复制或移动构造函数,并且
- 它的所有非静态数据成员和基类都是非易失性文字类型.
奖励积分;)用于回答if
constexpr std::initializer_list<int> my_list = {1,2,3,4,5};
Run Code Online (Sandbox Code Playgroud)
是合法的(有参考).虽然我认为上述+ [dcl.init.list]/5涵盖了这一点
在类定义中初始化静态整型数据成员可以声明const或constexpr,但在类定义中初始化非整数的静态数据成员必须是constexpr:
class MyClass {
static const int w = 5; // okay
static constexpr int x = 5; // okay
static const float y = 1.5; // error!
static constexpr float z = 1.5; // okay
};
Run Code Online (Sandbox Code Playgroud)
有人知道为什么不允许y的声明吗?标准中将其定为非法的部分是9.4.2/3,但为什么它是非法的?
假设我有一个类X,哪个功能需要很多常量表值,比如一个数组A[1024].我有一个f计算其值的重复函数,就像
A[x] = f(A[x - 1]);
Run Code Online (Sandbox Code Playgroud)
假设这A[0]是一个已知常量,因此数组的其余部分也是常量.使用现代C++的功能预先计算这些值的最佳方法是什么,并且没有使用此数组的硬编码值存储文件?我的解决方法是一个const静态虚拟变量:
const bool X::dummy = X::SetupTables();
bool X::SetupTables() {
A[0] = 1;
for (size_t i = 1; i <= A.size(); ++i)
A[i] = f(A[i - 1]);
}
Run Code Online (Sandbox Code Playgroud)
但我相信,这不是最美好的方式.注意:我强调数组相当大,我想避免代码的怪异.
为什么constexpr函数在编译时没有被评估,而是在main函数的return语句中运行时?
它试过了
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
const int x = fac<3>();
return x;
}
Run Code Online (Sandbox Code Playgroud)
结果是
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 6
mov eax, 6
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
与gcc 8.2.但是当我在return语句中调用该函数时
template<int x>
constexpr int fac() {
return fac<x - 1>() * x;
}
template<>
constexpr int fac<1>() {
return 1;
}
int main() {
return fac<3>(); …Run Code Online (Sandbox Code Playgroud) 现有元组重载std::get仅限于按索引或类型返回 1 个元素。想象一下,有一个包含多个相同类型元素的元组,并且您希望将它们全部提取到一个新元组中。
std::get<T>如何实现像这样返回给std::tuple定类型的所有出现的版本?
template<typename... Ts_out>
constexpr std::tuple<Ts_out...> extract_from_tuple(auto& tuple) {
// fails in case of multiple occurences of a type in tuple
return std::tuple<Ts_out...> {std::get<Ts_out>(tuple)...};
}
auto tuple = std::make_tuple(1, 2, 3, 'a', 'b', 'c', 1.2, 2.3, 4.5f);
auto extract = extract_from_tuple <float, double>(tuple);
// expecting extract == std::tuple<float, double, double>{4.5f, 1.2, 2.3}
Run Code Online (Sandbox Code Playgroud)
不确定按std::make_index_sequence元素访问每个元素是否可行。std::get<index>std::is_same_v
我是对的,那个:
constexpr都是纯函数,和constexpr如果编译器的价格不是很高,那么任何纯函数都可以并且必须定义.如果是这样,为什么不<cmath>定义函数constexpr?
是constexpr编译器的指标还是强制执行行为?
手头的例子如下:
template<typename T>
std::size_t constexpr getID() { return typeid(T).hash_code(); }
Run Code Online (Sandbox Code Playgroud)
hash_code是一个运行时常量,但即使请求编译时评估,此片段也会编译constexpr.只有在期望编译时常量的返回值之后,才会注意到这不能用作constexpr函数.
那么是constexpr一个"提示"(很像inline关键字)或编译器的"绑定请求"?
不幸的是,我有点困惑constexpr,在头文件中声明的全局常量和odr.
简而言之:我们可以从这里结束
https://isocpp.org/files/papers/n4147.pdf
那
constexpr MyClass const MyClassObj () { return MyClass {}; }
constexpr char const * Hello () { return "Hello"; }
Run Code Online (Sandbox Code Playgroud)
比...好
constexpr MyClass const kMyClassObj = MyClass {};
constexpr char const * kHello = "Hello";
Run Code Online (Sandbox Code Playgroud)
如果我想"只使用"那些全局声明/定义的实体并且不想考虑我如何使用它们,那么在头文件中定义全局变量?
假设我有一些功能模板f1:
template<typename f2>
int f1(int i, int j) noexcept {
return i + j + f2(i, j);
}
Run Code Online (Sandbox Code Playgroud)
有没有办法确定是否f2(i, j)可以constexpr.(无论它是函数还是函子),所以也标记f1<f2>为constexpr?
我想在这里使用SFINAE一些如何,但没有找到如何检测constexpr使用类型特征
我正在尝试编写一个constexpr表单的函数:
constexpr int foo(bool cond) {
int a, b, c;
if (cond) {
a = 1;
b = 2;
c = 3;
}
else {
a = -1;
b = -2;
c = -3;
}
return a + b + c;
}
Run Code Online (Sandbox Code Playgroud)
但是,编译器抱怨我使用了未初始化的变量,尽管事实上保证了局部变量的最终初始化.
我可以重新编写函数来使用三元运算符,即int a = cond ? 1 : -1;等等,但我不愿意.有没有办法说服编译器初始化局部变量?