这是这个问题的后续问题:声明constexpr initializer_list对象是否合法?.
从C++ 14开始,std::initializer_list该类的所有方法都标有constexpr.能够通过执行来初始化实例似乎很自然,
constexpr std::initializer_list<int> list = {1, 2, 3};
但是Clang 3.5抱怨list没有被常量表达式初始化.
正如dyp在评论中指出的那样,任何std::initializer_list文字类型的要求似乎都从规范中消失了.
如果我们甚至不能将类完全定义为constexpr,那么有什么意义呢?这是标准中的疏忽,将来会得到修复吗?
在你问之前,我已经在SO上寻找并寻找了这个,但是找不到可靠的答案.
我需要能够动态迭代具有非增量值的枚举,例如:
typedef enum {
CAPI_SUBTYPE_NULL = 0, /* Null subtype. */
CAPI_SUBTYPE_DIAG_DFD = 1, /* Data Flow diag. */
CAPI_SUBTYPE_DIAG_ERD = 2, /* Entity-Relationship diag. */
CAPI_SUBTYPE_DIAG_STD = 3, /* State Transition diag. */
CAPI_SUBTYPE_DIAG_STC = 4, /* Structure Chart diag. */
CAPI_SUBTYPE_DIAG_DSD = 5, /* Data Structure diag. */
CAPI_SUBTYPE_SPEC_PROCESS = 6, /* Process spec. */
CAPI_SUBTYPE_SPEC_MODULE = 7, /* Module spec. */
CAPI_SUBTYPE_SPEC_TERMINATOR = 8, /* Terminator spec. */
CAPI_SUBTYPE_DD_ALL = …Run Code Online (Sandbox Code Playgroud) 在以下代码中(在本地和Wandbox上测试):
#include <iostream>
enum Types
{
A, B, C, D
};
void print(std::initializer_list<Types> types)
{
for (auto type : types)
{
std::cout << type << std::endl;
}
}
int main()
{
constexpr auto const group1 = { A, D };
print(group1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
MSVC 15.8.5无法编译:
error C2131: expression did not evaluate to a constant
note: failure was caused by a read of a variable outside its lifetime
note: see usage of '$S1'
Run Code Online (Sandbox Code Playgroud)
(均指含有的行constexpr)
Clang 8(HEAD)报道:
error: constexpr …Run Code Online (Sandbox Code Playgroud) 灵感来自这个答案,来自[expr.const]
常量表达式是glvalue核心常量表达式,它指的是一个实体,它是常量表达式的允许结果(如下所定义),或者是一个prvalue核心常量表达式,其值满足以下约束:
如果值是类类型的对象,则引用类型的每个非静态数据成员引用一个实体,该实体是常量表达式的允许结果,
如果值是指针类型,则它包含具有静态存储持续时间的对象的地址,超过此类对象末尾的地址([expr.add]),函数的地址或空指针值,以及
如果值是类或数组类型的对象,则每个子对象都满足这些值的约束.
如果实体是具有静态存储持续时间的对象,则该实体是常量表达式的允许结果,该对象不是临时对象,或者是其值满足上述约束的临时对象,或者它是函数.
什么是具有静态存储持续时间的临时对象?我是否遗漏了某些东西,或者说对象是暂时的并且具有静态存储持续时间是矛盾的吗?
来自[basic.stc.static]的定义
所有没有动态存储持续时间,没有线程存储持续时间且不是本地的变量都具有静态存储持续时间.这些实体的存储应持续该计划的持续时间
仅适用于变量.
我正在寻找创建一个坐标查找表,如:
int a[n][2] = {{0,1},{2,3}, ... }
Run Code Online (Sandbox Code Playgroud)
对于给定的n,在编译时创建.我开始研究constexpr,但似乎是一个函数返回a constexpr std::vector<std::array <int, 2> >不是一个选项,因为我得到:
invalid return type 'std::vector<std::array<int, 2ul> >' of constexpr function
Run Code Online (Sandbox Code Playgroud)
如何创建这样的编译时数组?
以下程序在 GCC 和 Clang 中编译时不会发出警告,并产生预期的输出:
#include <initializer_list>
#include <iostream>
constexpr std::initializer_list<std::initializer_list<const char*>> list = {
{"a", "b", "c"},
{"d"}
};
int main() {
for (const auto& outer: list) {
std::cout << "level:\n";
for (const auto& inner: outer) {
std::cout << " " << inner << "\n";
}
}
}
Run Code Online (Sandbox Code Playgroud)
然而,使用 MSVC,该程序根本不会产生任何输出。
根据 C++ 标准,该程序有效吗?这是 MSVC 中的错误吗?如果这不是有效的 C++ 那么为什么 GCC 或 Clang 没有发出警告?有没有更好的方法来创建constexpr内部列表没有固定大小的嵌套列表?
我正在玩索引技巧,看看我可以去哪里,并遇到一个奇怪的错误...首先,简单的不那么老的指数:
template<std::size_t...>
struct indices {};
template<std::size_t N, std::size_t... Indices>
struct make_indices:
make_indices<N-1, N-1, Indices...>
{};
template<std::size_t... Indices>
struct make_indices<0, Indices...>:
indices<Indices...>
{};
Run Code Online (Sandbox Code Playgroud)
我创建了一个从a派生的编译时数组类std::initializer_list,并使其具有可索引性(假设N3471支持您的编译器.无论如何它将在下一个标准中).这里是:
template<typename T>
struct array:
public std::initializer_list<T>
{
constexpr array(std::initializer_list<T> values):
std::initializer_list<T>(values)
{}
constexpr auto operator[](std::size_t n)
-> T
{
return this->begin()[n];
}
};
Run Code Online (Sandbox Code Playgroud)
所以,我尝试创建一个函数,array在每个成员添加1后返回一个副本:
template<typename T, std::size_t... I>
auto constexpr add_one(const array<T>& a, indices<I...>)
-> const array<T>
{
return { (a[I]+1)... };
}
Run Code Online (Sandbox Code Playgroud)
并完成代码,这是我的主要:
int main()
{
constexpr array<int> a = …Run Code Online (Sandbox Code Playgroud)