选择模板参数包中的每个偶数(或奇数)参数
Select every even (or odd) argument in template parameter pack
我想允许使用我正在编写的类来指定类型列表和这些类型的分配器列表作为模板参数,方法是类型位于奇数位置,分配器位于偶数位置:
template<typename... T>
class MyClass {
// Stuff inside
}
int main() {
MyClass<SomeType1, AllocatorOfSomeType1> c1;
MyClass<SomeType1, AllocatorOfSomeType1,
SomeType2, AllocatorOfSomeType2> c2;
MyClass<SomeType1, AllocatorOfSomeType1,
SomeType2, AllocatorOfSomeType2,
SomeType3, AllocatorOfSomeType3> c3;
// And so on....
}
在内部,有一个类型为的向量元组进行存储是有意义的
std::tuple<std::vector<EveryOddTypeInParameterPack>...> m_storage_;
和一个用于使用的分配器元组:
std::tuple<std::vector<EveryEvenTypeInParameterPack>...> m_storage_;
我该如何在代码中声明这些元组?理论上,我需要以某种方式选择参数包中的每个奇数/偶数类型——这可能吗?
虽然代码有点长,但我认为该机制没有不必要的特性
如果我正确理解这个问题,以下代码可能会达到目的:
// push front for tuple
template< class, class > struct PFT;
template< class A, class... T > struct PFT< A, tuple< T... > > {
typedef tuple< A, T... > type;
};
// for even
template< class... > struct even_tuple;
template< class A, class B > struct even_tuple< A, B > {
typedef tuple< A > type;
};
template< class A, class B, class... T > struct even_tuple< A, B, T... > {
typedef typename PFT< A, typename even_tuple< T... >::type >::type type;
};
// As for odd elements, in the same way as even(please see the test on ideone)
// objective type
template< class > struct storage_type;
template< class... T > struct storage_type< tuple< T... > > {
typedef tuple< vector< T >... > type;
};
template< class... T >
struct MyClass {
typename storage_type< typename even_tuple< T... >::type >::type
m_storage_even_;
typename storage_type< typename odd_tuple< T... >::type >::type
m_storage_odd_;
};
这是一个关于ideone的测试。
也许是这样的:
#include <tuple>
// Example receptacle
template <typename ...Args> struct MyContainer;
// Tuple concatenator
template<typename PackR, typename PackL> struct cat;
template<typename ...R, typename ...L>
struct cat<std::tuple<R...>, std::tuple<L...>>
{
typedef std::tuple<R..., L...> type;
};
// Even/Odd extractors
template <typename ...Args> struct GetEven;
template <typename ...Args> struct GetOdd;
template <typename E1, typename O1, typename ...Args>
struct GetEven<E1, O1, Args...>
{
typedef typename cat<std::tuple<E1>, typename GetEven<Args...>::value>::type value;
};
template <typename E1, typename O1>
struct GetEven<E1, O1>
{
typedef std::tuple<E1> value;
};
template <typename E1, typename O1, typename ...Args>
struct GetOdd<E1, O1, Args...>
{
typedef typename cat<std::tuple<O1>, typename GetEven<Args...>::value>::type value;
};
template <typename E1, typename O1>
struct GetOdd<E1, O1>
{
typedef std::tuple<O1> value;
};
// Tuple-to-Receptacle mover
template <typename Pack, template <typename ...T> class Receiver> struct Unpack;
template <typename ...Args, template <typename ...T> class Receiver>
struct Unpack<std::tuple<Args...>, Receiver>
{
typedef Receiver<Args...> type;
};
// Example consumer
template <typename ...Args>
struct Foo
{
typedef typename Unpack<typename GetEven<Args...>::value, MyContainer>::type EvenVector;
typedef typename Unpack<typename GetOdd<Args...>::value, MyContainer>::type OddVector;
EvenVector x;
OddVector y;
};
你仍然需要定义你的MyContainer
类来对变参数做一些有用的事情,例如实现你的向量元组。。。(为什么不是元组的向量呢?)
归功于brunocodutra的元组技巧。
这只是一个尝试
template<typename... T> class Myclass;
template<typename T1, typename allocT1>
class MyClass <T1, allocT1> {
std::pair<T1, allocT1> myFirstArglist;
//and you have to do a check that allocT1::value_type is same as T1 or not
//or may be alloT1 is an allocator type or not(i'm thinking concepts, may be)
//this idea is inspired from Chris's comment
};
template<typename T1, typename allocT1, typename... T>
class Myclass<T1, allocT1, T...> {
std::pair<T1, allocT1> myFirstArglist;
Myclass<T>; //something like this
};
template<>
class Myclass<> {
//probably you would like some error message here
//when there are no types and containers
};
可能是我不够清楚,你可能想看看http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2080.pdf
还有一篇关于分配器类型设计的好文章。。。您想看看:分配器类型参数的C++设计模式
我知道你的问题最初被标记为"c++11",但我认为值得为子孙后代指出的是,在c++14中,你可以访问make_index_sequence
,这使得整个事情变得非常简单。对于筛选元组,我将从以下大纲开始:https://quuxplusone.github.io/blog/2018/07/23/metafilter/
然后我们得到了这样的东西(Godbolt):
template<bool> struct zero_or_one {
template<class E> using type = std::tuple<E>;
};
template<> struct zero_or_one<false> {
template<class E> using type = std::tuple<>;
};
template<class Tuple, class = std::make_index_sequence<std::tuple_size<Tuple>::value>>
struct just_evens;
template<class... Es, size_t... Is>
struct just_evens<std::tuple<Es...>, std::index_sequence<Is...>> {
using type = decltype(std::tuple_cat(
std::declval<typename zero_or_one<Is % 2 == 0>::template type<Es>>()...
));
};
要获得just_odds
,您需要将条件从Is % 2 == 0
切换到Is % 2 != 0
。
示例用法:
static_assert(std::is_same<
just_evens<std::tuple<char, short, int, long, double>>::type,
std::tuple<char, int, double>
>::value, "");
相关文章:
- 参数包中的筛选器类型
- 实例化模板时,我是否必须显式显示参数包中的类型?
- C++ 在可变参数模板的参数包中并集参数?
- 如何检测参数包中的uint8_t类型
- 从函数参数包中删除最后一项
- C++:我可以在模板参数包中强制执行至少1个agment吗
- 这种获取模板参数包中最后一个元素的方法是否有隐藏的开销?
- 从参数包中排除前 n 个参数
- 如何在参数包中找到最大值
- 是否可以使用 Boost.Hana 将 std::array 解压缩到非类型模板参数包中
- 如何更改参数包中的最后一个参数
- 从参数包中派生的调用基类运算符 =
- C++17:对参数包中的模板进行通用(基于多重继承?)检查
- 如何获取参数包中元素的索引
- 如何从模板类的可变参数包中的每个类型恢复非类型名模板参数?
- 对参数包中的每个元素应用函数
- 如何检查参数包中的每个类型是否唯一
- 在参数包中获取函数指针的返回类型,并将其保存为与其他参数连接的元组
- 模板元编程:参数包中的模板参数数量错误
- 如何在模板方法内从参数包中移动unique_ptr