djf*_*jfm 5 c++ recursion templates variadic-templates c++11
我正在做一些可变参数的实验,我偶然发现了一个我无法弄清楚解决方案的问题 - 基本上我正在尝试用任意数据类型的组件构建一个树 - 这里有一些代码:
template <class A, class B>
struct SeqExpression
{
const A & first;
const B & then;
};
template <class A, class B>
SeqExpression<A,B>
make_seq(const A & a, const B & b)
{
return {a,b};
}
template <class A, class B, class ...T>
auto
make_seq(const A & first, const B & second, T ...rest) -> decltype(make_seq(make_seq(first,second),rest...))
{
return make_seq(make_seq(first,second),rest...);
}
Run Code Online (Sandbox Code Playgroud)
然后我尝试:
auto x = make_seq("X","Y",'z');
Run Code Online (Sandbox Code Playgroud)
但GCC(4.7)告诉我:
error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) substituting ‘template<class A, class B, class ... T> decltype (make_seq(make_seq(first, second), rest ...)) make_seq(const A&, const B&, T ...) [with A = SeqExpression<char [2], char [2]>; B = char; T = {}]’
recursively required by substitution of ‘template<class A, class B, class ... T> decltype (make_seq(make_seq(first, second), rest ...)) make_seq(const A&, const B&, T ...) [with A = SeqExpression<char [2], char [2]>; B = char; T = {}]’
required by substitution of ‘template<class A, class B, class ... T> decltype (make_seq(make_seq(first, second), rest ...)) make_seq(const A&, const B&, T ...) [with A = char [2]; B = char [2]; T = {char}]’
Run Code Online (Sandbox Code Playgroud)
在我看来,它应该是可以解决的!
make_seq("X","Y")有类型SeqExpression< char[2],char[2] >
所以make_seq(make_seq("X","Y"),'z')有类型SeqExpression< SeqExpression< char[2],char[2] >,char >
而且对我来说似乎相对来说不是那么吵闹.
有什么想法吗?
问题是,当您有两个参数(在两个参数模板上)时,您的可变参数模板就会被选择。您需要确保仅当您有至少三个参数时才选择它;最简单的方法是添加另一个参数:
template <class A, class B, class C, class ...T>
auto
make_seq(const A & first, const B & second, const C &third, T ...rest)
-> decltype(make_seq(make_seq(first,second), third, rest...))
{
return make_seq(make_seq(first,second), third, rest...);
}
Run Code Online (Sandbox Code Playgroud)
可变参数包可以并且将会匹配零个参数;这可能看起来令人惊讶,但它比其他选择更好。
请注意,上面显然利用了返回类型的非标准 g++ 扩展。以下类型程序应该能够计算与参数序列对应的类型:
template <int n, class ...T> struct mst_helper;
template <class A, class B>
struct mst_helper<2, A, B> { typedef SeqExpression<A, B> type; };
template <int n, class A, class B, class ...T>
struct mst_helper<n, A, B, T...> {
typedef typename mst_helper<n - 1, SeqExpression<A, B>, T...>::type type; };
template <class ...T>
struct make_seq_type { typedef typename mst_helper<sizeof...(T), T...>::type type; };
template <class A, class B, class C, class ...T>
typename make_seq_type<A, B, C, T...>::type
make_seq(const A & first, const B & second, const C &third, T ...rest)
{
return make_seq(make_seq(first,second), third, rest...);
}
Run Code Online (Sandbox Code Playgroud)
g++-4.7.1 似乎有模板别名的错误,所以我不得不使用struct而不是using.
| 归档时间: |
|
| 查看次数: |
813 次 |
| 最近记录: |