问题描述
|
我想允许使用我正在编写的类将类型列表以及这些类型的分配器列表指定为模板参数,以使类型位于奇数位置而分配器处于偶数位置:
template<typename... T>
class MyClass {
// Stuff inside
}
int main() {
MyClass<SomeType1,AllocatorOfSomeType1> c1;
MyClass<SomeType1,AllocatorOfSomeType1,SomeType2,AllocatorOfSomeType2> c2;
MyClass<SomeType1,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 ...Args>
struct GetOdd<E1,Args...>
{
typedef typename cat<std::tuple<O1>,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
,请将条件从from10ѭ切换到Is % 2 != 0
。
用法示例:
static_assert(std::is_same<
just_evens<std::tuple<char,short,int,long,double>>::type,std::tuple<char,double>
>::value,\"\");