我对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'不是常量表达式
我想利用递归对列表中的每个模板参数执行相等检查,如果它们全部相等则返回其中一个。
答案 0 :(得分:2)
这是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>;
}
上查看
答案 1 :(得分:2)
或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
}
已编辑:all_of
受到Jarod42的启发。
答案 2 :(得分:2)
参数不是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$
}
}