可变参数模板参数的元迭代
Meta-iteration over variadic templates arguments
我想概括以下模式:
template<class A1, class A2, class A3>
class Foo {
protected:
template<class T>
void foo(const T& t) {...do stuff...}
public:
void bar(const A1& a) { foo(a); }
void bar(const A2& a) { foo(a); }
void bar(const A3& a) { foo(a); }
};
上述方法不能随着许多增加的参数而扩展。所以,我想做:
template<class As...>
class Foo {
protected:
template<class T>
void foo(const t& a) {...do stuff...}
public:
for each type A in As declare:
void bar(const A& a) { foo(a); }
};
有没有办法做到这一点?
另一种方法是在bar
进行检查以测试类型是否在序列中,否则barf带有有用的错误消息,这样可以避免任何继承技巧。
#include <iostream>
struct E {};
struct F {};
template <class... As>
class Foo
{
template <typename U>
static constexpr bool contains() {
return false;
}
template <typename U, typename B, typename ...S>
static constexpr bool contains() {
return (std::is_same<U, B>::value)? true : contains<U, S...>();
}
protected:
template <class T>
void foo(const T& a) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
public:
template <class T>
void bar(const T& a) {
static_assert(contains<T, As...>(), "Type does not exist");
foo(a);
}
};
int main()
{
Foo<E, F, E, F> f;
f.bar(F{});
f.bar(E{});
f.bar(1); // will hit static_assert
}
如果您实际上不需要 bar
s,而只需要约束foo
- 我们可以使用 SFINAE 仅允许使用可转换为A
之一的类型调用它:
template <class... As>
class Foo {
public:
template <class T,
class = std::enable_if_t<any<std::is_convertible<T, As>::value...>::value>>
void foo(T const&) { ... }
};
我们可以使用类似bool_pack
技巧来实现any
:
template <bool... b> struct bool_pack { };
template <bool... b>
using any = std::integral_constant<bool,
!std::is_same<bool_pack<b..., false>, bool_pack<false, b...>>::value>;
template <class CRTP, class A, class... As>
struct FooBar
{
void bar(const A& a)
{
static_cast<CRTP*>(this)->foo(a);
}
};
template <class CRTP, class A, class B, class... As>
struct FooBar<CRTP, A, B, As...> : FooBar<CRTP, B, As...>
{
using FooBar<CRTP, B, As...>::bar;
void bar(const A& a)
{
static_cast<CRTP*>(this)->foo(a);
}
};
template <class... As>
class Foo : FooBar<Foo<As...>, As...>
{
template <class, class, class...>
friend struct FooBar;
protected:
template <class T>
void foo(const T& a) { }
public:
using FooBar<Foo, As...>::bar;
};
演示
template <class A, class... As>
class Foo : public Foo<As...>
{
protected:
using Foo<As...>::foo;
public:
using Foo<As...>::bar;
void bar(const A& a) { foo(a); }
};
template <class A>
class Foo<A>
{
protected:
template <class T>
void foo(const T& t) { }
public:
void bar(const A& a) { foo(a); }
};
与 Piotr Skotnicki 的答案类似,这使用继承来构建一个类,其中包含所有模板参数的重载bar
。 不过它更干净一些,只有一个类模板加上部分专业化。
template<class A, class Foo_t>
class bar_t {
public:
void bar(const A &a) { Foo_t::foo(a); }
};
template<class ...As>
class Foo : bar_t<As, Foo<As...> >... {
protected:
template<class T>
void foo(const T& a) { /* do stuff */ }
};
相关文章:
- 如何在C++中将迭代器作为函数参数传递
- 定义模板参数的迭代器类型
- 当通知迭代器参数初始化为空列表的开头时,list::insert 行为是什么?
- 具有C++迭代器参数的多功能函数
- C++如何获取传递给函数(STL 迭代器)的参数的名称
- 如何迭代作为指针传递的对数组参数
- 当迭代器(输入参数)通常不是constexpr时,constexpr算法真的有用吗
- 迭代器的模板参数:函数在调用时推断类型?
- 接受迭代器作为参数并存储值的类?
- 我的代码在作为参数传入 .begin() 时不起作用,但在我将 .begin() 转换为迭代器后工作
- 如何使用迭代器作为参数方法?
- 调用模板函数的问题"No matching function for call"参数:迭代器、对象函数
- 使用 std::vector<Particle> 粒子;函数 .at() 不能与迭代器一起使用,它作为 for 循环中的参数
- 如何确保函数模板的参数是随机访问迭代器
- 让宏将迭代参数传递到通过宏变量提供的代码体中
- 使用迭代器和可变参数模板的笛卡尔乘积
- 从具有迭代器参数的模板函数返回指针
- 迭代C++可变参数模板
- 如何使用std:字符串参数迭代variadic函数
- C++ 可变参数模板参数迭代