Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.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++ 具有初始值设定项\u列表的编译时查找表_C++_C++17 - Fatal编程技术网

C++ 具有初始值设定项\u列表的编译时查找表

C++ 具有初始值设定项\u列表的编译时查找表,c++,c++17,C++,C++17,假设您有一些散列值,并希望在编译时将它们映射到各自的字符串。 理想情况下,我希望能够写一些大致如下的内容: constexpr std::map={{1,1},{2,2}; 不幸的是,这在C++17和C++2a中都是不可能的。然而 我试着用std::array模拟这一点,但在编译时无法获得初始值设定项列表的大小,以便在没有明确指定大小的情况下正确设置数组的类型。 这是我的模型: 模板 结构cxpair { 使用第一种类型=T0; 使用第二种类型=T1; //有趣的是,我们不能因为某种原因而违

假设您有一些散列值,并希望在编译时将它们映射到各自的字符串。 理想情况下,我希望能够写一些大致如下的内容:

constexpr std::map={{1,1},{2,2};
不幸的是,这在C++17和C++2a中都是不可能的。然而 我试着用
std::array
模拟这一点,但在编译时无法获得初始值设定项列表的大小,以便在没有明确指定大小的情况下正确设置数组的类型。 这是我的模型:


模板
结构cxpair
{
使用第一种类型=T0;
使用第二种类型=T1;
//有趣的是,我们不能因为某种原因而违约。。。
constexpr cxpair()
:first(),second()
{  }
constexpr cxpair(第一种类型和第一种类型,第二种类型和第二种类型)
:第一(第一)、第二(第二)
{  }
//std::pair没有这些作为constexpr
constexpr cxpair&operator=(cxpair&other)
{first=other.first;second=other.second;返回*this;}
constexpr cxpair和operator=(const cxpair和其他)
{first=other.first;second=other.second;返回*this;}
T0第一;
T1秒;
};
模板
结构图
{
使用键类型=键;
使用映射的类型=值;
使用value_type=cxpair;
constexpr映射(std::initializer\u列表)
:映射(list.begin(),list.end())
{  }
模板
常量表达式映射(Itr开始、常量Itr和结束)
{
std::size\u t size=0;
while(开始!=结束){
如果(大小>=大小){
抛出std::range_错误(“索引超过内部数据大小的末尾”);
}否则{
自动&v=数据[size++];
v=标准::移动(*开始);
}
++开始;
}
}
//…省略了有用的实用方法
私人:
std::数组数据;
//对于实用程序,为了简洁起见,还可以省略一个size成员
};
现在,如果您只使用普通的
std::array
操作,那么一切都是开箱即用的:


constexpr std::数组mapp={{{1,1},{2,2}};
//即使是普通双
constexpr std::数组mapp={{{1,1},{2,2}};
不幸的是,我们必须明确给出数组的大小作为第二个模板参数。这正是我想要避免的。 为此,我试着绘制了你在上面看到的地图。 有了这个伙伴,我们可以写一些东西,比如:

constexpr-map-mapq={{1,1};
constexpr映射mapq={{1,1},{2,2};
不幸的是,一旦我们超过映射中的magic
Size
常量,我们就会得到一个错误,因此我们需要明确给出大小:

///我希望它在没有其他恶作剧的情况下工作:
//constexpr映射mapq={{1,1},{2,2},{3,3};
constexpr映射mapq={{1,1},{2,2},{3,3};
当然,只要
在constexpr范围内抛出
,就会出现编译错误,可以显式地调整magic常量。然而,这是我想隐藏的一个实现细节。用户不需要处理这些低级细节,这是编译器应该推断出来的

不幸的是,我没有看到一个具有确切语法的解决方案
map={…}
。我甚至看不到像
constexpr auto-map=make_-map({…})。此外,这是一个不同于运行时的API,我希望避免使用它以增加易用性

那么,是否有可能在编译时从初始值设定项列表中推断出此大小参数?

有一个推断指南:

template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
允许:

// ok, m is map<int, int, 3>
constexpr map m = {std::pair{1, 1}, std::pair{1, 2}, std::pair{2, 3}};
这样可以避免编写扣减指南,并且只需在第一个上写入类型,而需要额外的一对大括号或括号:

// ok, n is map<int, int, 4>
constexpr map n{{std::pair{1, 1}, {1, 2}, {2, 3}, {3, 4}}};

// same
constexpr map n({std::pair{1, 1}, {1, 2}, {2, 3}, {3, 4}});
//好的,n是map
constexpr映射n{{std::pair{1,1},{1,2},{2,3},{3,4}};
//同样的
constexpr映射n({std::pair{1,1},{1,2},{2,3},{3,4});

注意,数组是
而不是
——这允许只写入
对{1,1}
。既然您正在编写一个
constexpr
映射,那么这种区别可能并不重要

@Barry的回答为我指明了正确的方向。总是在列表中明确列出
,这是不可取的。此外,我希望能够部分专门化
map
的模板参数列表。考虑下面的例子:

//为了便于示例,假设这是可行的
constexpr映射n({1,1},{2,2}});
//->decltype(n)=map
//下面的方法行不通
constexpr映射m({1,1},{2,2}});
但是,用户可能希望映射包含
std::size\t
作为键,而不是文本。i、 e.s/他必须定义一个用户定义的文本才能做到这一点

我们可以通过将工作转移到
make_map
函数来解决这个问题,允许我们对map进行部分专门化:

//映射的数组构造函数的推导指南
模板
map(cxpair(&&)[Size])->map;
//make_map构建地图
模板
constexpr自动生成映射(cxpair(&&m)[Size])->映射
{返回映射(std::begin(m),std::end(m));}
//让我们做到:
constexpr auto-mapr=make_-map({1,1}),
{2, "2"},
{3, "3"} });

显示的映射的初始化错误,您应该切换整数和字符串。听起来有点像。是否要获取已知值集的快速反向哈希?你真的需要它吗?您的实际问题是什么?另外,请向我们展示您在
std::array
上的尝试,我已经相应地编辑了我的问题。如果还有什么不清楚的地方,请告诉我。@JHBonarius对于字符串文字来说没问题。第一种解决方案太麻烦了。不幸的是,第二种解决方案的缺点是用户不能部分地专门化
map// ok, m is map<int, int, 3>
constexpr map m = {std::pair{1, 1}, std::pair{1, 2}, std::pair{2, 3}};
template <typename Key, typename Value, std::size_t Size>
struct map {
    constexpr map(std::pair<Key, Value>(&&)[Size]) { }
};
// ok, n is map<int, int, 4>
constexpr map n{{std::pair{1, 1}, {1, 2}, {2, 3}, {3, 4}}};

// same
constexpr map n({std::pair{1, 1}, {1, 2}, {2, 3}, {3, 4}});