2010-05-17 131 views
1

我想将传递给可变参数模板的模板参数填充到固定长度的数组中。为此目的,我写了下面的辅助函数模板用模板参数填充容器

template<typename ForwardIterator, typename T> 
void fill(ForwardIterator i) { } 

template<typename ForwardIterator, typename T, T head, T... tail> 
void fill(ForwardIterator i) { 
    *i = head; 
    fill<ForwardIterator, T, tail...>(++i); 
} 

下面的类模板

template<typename T, T... args> 
struct params_to_array; 

template<typename T, T last> 
struct params_to_array<T, last> { 
    static const std::size_t SIZE = 1; 
    typedef std::array<T, SIZE> array_type; 

    static const array_type params; 

private: 
    void init_params() { 
    array_type result; 
    fill<typename array_type::iterator, T, head, tail...>(result.begin()); 
    return result; 
    } 
}; 

template<typename T, T head, T... tail> 
struct params_to_array<T, head, tail...> { 
    static const std::size_t SIZE = params_to_array<T, tail...>::SIZE + 1; 
    typedef std::array<T, SIZE> array_type; 

    static const array_type params; 

private: 
    void init_params() { 
    array_type result; 
    fill<typename array_type::iterator, T, last>(result.begin()); 
    return result; 
    } 
}; 

,并通过

template<typename T, T last> 
const typename param_to_array<T, last>::array_type 
param_to_array<T, last>::params = 
    param_to_array<T, last>::init_params(); 

template<typename T, T head, T... tail> 
const typename param_to_array<T, head, tail...>::array_type 
param_to_array<T, head, tail...>::params = 
    param_to_array<T, head, tail...>::init_params(); 

初始化静态常量现在该阵列

param_to_array<int, 1, 3, 4>::params 

std::array<int, 3>和包含值134。我认为必须有一种更简单的方法来实现这种行为。有什么建议么?

编辑:诺亚·罗伯茨在他的回答建议我修改我的程序如下所示:我写了一个新的结构计算的参数列表中的元素:

template<typename T, T... args> 
struct count; 

template<typename T, T head, T... tail> 
struct count<T, head, tail...> { 
    static const std::size_t value = count<T, tail...>::value + 1; 
}; 

template<typename T, T last> 
stuct count<T, last> { 
    static const std::size_t value = 1; 
}; 

,并写了下面的功能

template<typename T, T... args> 
std::array<T, count<T, args...>::value> 
params_to_array() { 
    std::array<T, count<T, args...>::value> result; 
    fill<typename std::array<T, count<T, args...>::value>::iterator, 
     T, args...>(result.begin()); 
    return result; 
} 

现在我得到

params_to_array<int, 10, 20, 30>() 

a std::array<int, 3>,内容10,2030。还有什么建议?

回答

2

无需手动计算参数包中的类型数量,即运营商的用途。此外,我会做的迭代器类型为fill()抵扣,没有必要明确指定:但是

template<typename T, typename FwdIt> 
void fill(FwdIt it) { } 

template<typename T, T head, T... tail, typename FwdIt> 
void fill(FwdIt it) { 
    *it = head; 
    fill<T, tail...>(++it); 
} 

template<class T, T... args> 
std::array<T, sizeof...(args)> params_to_array() { 
    std::array<T, sizeof...(args)> a; 
    fill<T, args...>(a.begin()); 
    return a; 
}; 

参数包也是可扩展的初始化列表上下文,这使得fill()冗余:

template<class T, T... args> 
std::array<T, sizeof...(args)> params_to_array() { 
    std::array<T, sizeof...(args)> a = {{args...}}; 
    return a; 
}; 
+0

+1太棒了!我根本不知道'sizeof ...(args)'。 – phlipsy 2010-05-19 12:33:16

1

,我可以看到在param_to_array端的专业化的唯一原因是这一行:

static const std::size_t SIZE = params_to_array<T, tail...>::SIZE + 1; 

由于您params_to_array元函数创建好像你会最终实例的大小为N,N阵列的阵列-1,....,1.因此,我认为你的对象可以使用组合和单一责任规则的一些帮助。创建另一个可以计算参数列表中元素的元函数,并使用它代替此方法。然后你至少可以在params_to_array中摆脱这种递归。

+0

你是对的!我修改了(并因此简化了)我的程序,它工作。 +1! – phlipsy 2010-05-17 19:20:21

+0

不需要另一个元函数,只需在C++ 0x中使用'sizeof ...(parameterPack)'而不是:) – 2010-05-18 22:30:13