递归模板参数包编程
Recursive template parameter pack programming
我是C 模板编程的新手。我想设计一个函数element
,例如,例如
-
element<3, 3, 3, 3, 3>
将返回3 -
element<3, 3, 2>
将失败#include <iostream> #include <cstdlib> namespace meta { template<typename T> constexpr T element(T x) { return x; } template<typename T, typename... Ts> constexpr T element(T x, Ts... xs) { constexpr T oth = element(xs...); // $C$ static_assert(oth == x, "element Mismatch"); return x; } template<int... DIMS> void get_elements() { std::cout << "elements " << element(DIMS...); // $A$ } } int main(int argc, char ** argv) { meta::get_elements<2, 3, 4>(); // $B$ static constexpr int D1 = 3, D2 = 3; meta::get_elements<D1, D2>(); }
但是,使用
的std=c++14
的GCC失败在实例化'constexpr t meta :: element(t,ts ...([带t = int;ts = {int,int}]’:
$ a $:需要‘void meta :: get_elements(([with int ... dims = {2,3,4}]’
$ b $:此处需要
$ c $:错误:‘xs#0'不是常数表达式
$ c $:错误:‘xs#1'不是常数表达式
我想利用递归以对列表中的每个模板参数执行平等检查,如果它们都相等,则返回其中一个。
参数不是 constexpr
。
您可以使用std::integral_constant
绕过该
namespace meta
{
template<typename T, T V>
constexpr std::integral_constant<T, V> element(std::integral_constant<T, V>)
{
return {};
}
template<typename T, T V, typename... Ts>
constexpr std::integral_constant<T, V> element(std::integral_constant<T, V> x, Ts... xs)
{
constexpr auto oth = element(xs...); // $C$
static_assert(oth() == x(), "element Mismatch");
return {};
}
template<int... DIMS>
void get_elements()
{
std::cout << "elements " << element(std::integral_constant<int, DIMS>{}...); // $A$
}
}
这是C 17中的一个简单解决方案:
template <int Head, int... Tail> struct element
{
static_assert((... && (Head == Tail)), "missmatch elements");
static constexpr auto value = Head;
};
template <int... I> constexpr auto element_v = element<I...>::value;
auto test()
{
// element_v<3, 3, 1>; // assert fail
constexpr int A = 3, B = 3;
return element_v<3, 3, A, B>;
}
在Godbolt上看到它
或pre-c 17(无递归(:
#include <iostream>
#include <cstdlib>
#include <type_traits>
namespace meta
{
template <bool...>
struct boolpack { };
template <bool... Bs>
struct all_of: std::is_same<boolpack<Bs..., true>, boolpack<true, Bs...>> { };
template<int FIRST, int... DIMS>
constexpr void get_elements()
{
static_assert(all_of<DIMS==FIRST...>::value, "!");
std::cout << "elements " << FIRST;
}
}
int main(int argc, char ** argv)
{
static constexpr int D1 = 3, D2 = 3;
meta::get_elements<D1, D2>();
//meta::get_elements<D1, D2, 2>(); //fail
}
[见Live]
编辑:all_of
受JAROD42启发。
相关文章:
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 模板元编程:如何将参数包组合成新的参数包
- Qt Q串行端口未编程设备未关闭
- 模板元编程 - 尝试实现维度分析
- 我是编程新手
- C++编程从外部文本文件定义数组大小
- 了解算法的性能差异(如果以不同的编程语言实现)
- 使用 Gtkmm 以编程方式选择 Gtk::TextView 中的文本
- 递归模板参数包编程
- 了解 UDP 数据包大小限制的 TCP 数据包大小限制以及它在 boost::asio 编程级别的含义
- 模板元编程:参数包中的模板参数数量错误
- 使用c++套接字编程的最大TCP数据包大小
- 如果我在 Windows 中编程我的深度数据包检测程序,我会错过什么主要的事情
- Clang 无法使用模板元编程编译参数包扩展
- 在 Windows 的 C++ 中编程数据包阻止程序(基本防火墙)
- 使用C++中的参数包进行函数式编程
- 关于数据包和缓冲区大小的TCP套接字编程
- 在嵌入式python 3中以编程方式定义包结构
- 参数包模板元编程深度优先搜索