【发布时间】:2014-03-15 20:23:37
【问题描述】:
在下面的代码中,我试图构建一个类型格。例如,在float 和int 之间,将结果提升为float:
float join(float f, int) { return f; }
float join(float f, float) { return f; }
那我介绍一个wrapper类型:
template <typename Inner>
struct wrapper
{
using inner_t = Inner;
inner_t value;
};
join 操作的行为非常自然:
template <typename Inner1, typename Inner2>
auto
join(const wrapper<Inner1>& w1, const wrapper<Inner2>& w2)
-> wrapper<decltype(join(w1.value, w2.value))>
{
return {join(w1.value, w2.value)};
}
它也可以是带有“标量”类型的joined:
template <typename Inner1, typename T2>
auto
join(const wrapper<Inner1>& w1, const T2& value2)
-> wrapper<decltype(join(w1.value, value2))>
{
return {join(w1.value, value2)};
}
到目前为止,一切都很好,它有效。但是,因为在实际情况中我实际上有更多这样的规则,所以我想避免重复规则的数量来表达join操作的交换性,因此,我表示join(scalar, wrapper) := join(wrapper, scalar)(实际上,我更喜欢join(v1, v2) := join(v2, v1) 之类的内容,但让我们从更具体的内容开始。):
template <typename T1, typename Inner2>
auto
join(const T1& value1, const wrapper<Inner2>& w2)
-> decltype(join(w2, value1))
{
return join(w2, value1);
}
这适用于join(scalar, scalar)、join(wrapper, scalar) 和join(scalar, wrapper)。但随后join(wrapper, wrapper) 导致模板函数在 G++ 4.9 和 Clang++ 3.5 中无限扩展,我不明白。
int main()
{
int i;
float f;
wrapper<float> fr;
join(f, i);
join(fr, i);
join(i, fr);
join(fr, fr); // Loops.
}
叮当声:
clang++-mp-3.5 -std=c++11 bar.cc
bar.cc:21:5: fatal error: recursive template instantiation exceeded maximum depth of
256
join(const wrapper<Inner1>& w1, const T2& value2)
^
bar.cc:29:5: note: while substituting deduced template arguments into function
template 'join' [with T1 = wrapper<float>, Inner2 = float]
join(const T1& value1, const wrapper<Inner2>& w2)
^
海合会:
g++-mp-4.9 -std=c++11 bar.cc
bar.cc:30:34: error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) substituting 'template<class T1, class Inner2> decltype (join(w2, value1)) join(const T1&, const wrapper<Inner2>&) [with T1 = <missing>; Inner2 = <missing>]'
-> decltype(join(w2, value1))
^
bar.cc:30:34: recursively required by substitution of 'template<class T1, class Inner2> decltype (join(w2, value1)) join(const T1&, const wrapper<Inner2>&) [with T1 = wrapper<float>; Inner2 = float]'
bar.cc:30:34: required by substitution of 'template<class T1, class Inner2> decltype (join(w2, value1)) join(const T1&, const wrapper<Inner2>&) [with T1 = wrapper<float>; Inner2 = float]'
bar.cc:43:18: required from here
我不明白为什么重载不会减少递归。到底是怎么回事? (类)模板专业化可能有一个可能的替代实现,但我不是在寻找替代实现:我想了解这个有什么问题。提前致谢。
【问题讨论】:
-
不是你的
join(wrapper, wrapper) = wrapper,join(wrapper, wrapper) = scalar暧昧吗?
标签: c++ c++11 overloading decltype trailing-return-type