Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ constexpr值的数据结构_C++_C++14_Template Meta Programming - Fatal编程技术网

C++ constexpr值的数据结构

C++ constexpr值的数据结构,c++,c++14,template-meta-programming,C++,C++14,Template Meta Programming,假设您有std::tuple和一个函数,该函数根据类型修改其上的值 模板 void modify(std::tuple和tuple、const T和value) { std::get(tuple)=值; } 现在假设,您希望记录这些函数调用,即记住元组中值的修改顺序。这里有一个简单的机制可以做到这一点 void日志(标准::大小索引) { 静态std::向量索引; 记录索引。向后推(索引) } 与以下助手 //计数直到T与第N种类型的元组相同 模板 结构元组类型索引impl; 模板 结构元组

假设您有
std::tuple
和一个函数,该函数根据类型修改其上的值

模板
void modify(std::tuple和tuple、const T和value)
{
std::get(tuple)=值;
}
现在假设,您希望记录这些函数调用,即记住元组中值的修改顺序。这里有一个简单的机制可以做到这一点

void日志(标准::大小索引)
{
静态std::向量索引;
记录索引。向后推(索引)
}
与以下助手

//计数直到T与第N种类型的元组相同
模板
结构元组类型索引impl;
模板
结构元组\u类型\u索引\u impl
{
静态constexpr std::size\u t value=N;
};
模板
结构元组\u类型\u索引\u impl
{
静态constexpr std::size\u t value=std::is\u same::value
N
:tuple\u type\u index\u impl::value;
};
//辅助变量
模板
constexpr std::size\u t tuple\u type\u index\u v=typename tuple\u type\u index\u impl::value;
我们可以有这种用法

模板
void modify(std::tuple和tuple、const T和value)
{
std::get(tuple)=值;
日志(元组类型索引);
}
这对于日志记录来说很好。但是假设您必须根据索引再次访问元组。我们可以使用开关将运行时索引转换为constexpr

开关(值)
{
案例0:返回std::get(元组);
案例1:返回std::get(tuple);
...
}
可以由编译器生成。但这真的是我们能做的最好的吗?在对log的调用中,
索引仍然是constexpr,因此我们可以将其移动到模板参数

模板
无效日志()
{
静态std::向量索引;
记录索引。向后推(索引);
}

但这不会有帮助,因为我们仍在将其传递给向量。我们可以(?)构建
std::index_序列,但最终会耗尽模板参数。我的一部分人认为这是不可能的,但另一部分人反对,因为
index
是constexpr。是否可以开发某种类型的
std::vector

要将
开关转换为“直接”呼叫,您可以执行以下操作:

template <typename ... Ts>
void print(const std::tuple<Ts...>& t, std::size_t index)
{
    if (sizeof...(Ts) < index) {
        throw std::runtime_error("invalid index");
    }
    using func_t = void (*)(const std::tuple<Ts...>&);
    func_t fs[] = { (+[](const std::tuple<Ts...>& t){
             std::cout << std::get<Ts>(t) << std::endl;
        })...
        // gcc dislikes that lambda,
        // but you can create template function instead
    };

    fs[index](t);
}
模板
无效打印(常量std::tuple&t,std::size\u t索引)
{
if(sizeof…(Ts)<索引){
抛出std::runtime_错误(“无效索引”);
}
使用func_t=void(*)(常量std::tuple&);
func_t fs[]={(+[](常量std::tuple&t){

std::cout这个开关或它的替代品是在日志函数中吗?例如,你想记录值和索引吗?@jwimberley我不介意值,只是访问值的索引。这个开关是由编译器使用类似的方法生成的,例如所示。你可以更改
tuple\u type\u index\u v
以返回
std::integral\u constant
,所以您仍然有编译时值。@Jarod42
tuple\u type\u index\u v
是编译时值。您想从向量内容中检索tuple元素,还是从
log
函数中检索tuple元素?我实际测试了它,性能与switch相同,所以编译器可以以某种方式优化它。