假设我有一对相关的模板,我想自动将参数从一个函数转换为另一个函数。我怎样才能做到这一点?
template<int a> struct bar;
template<int a, int b> struct foo {
operator bar<a> const (); // operator-based conversion
};
template<int a> struct bar : public foo<a, a> {
bar() { }
template<int b> bar(const foo<a, b>&) { } // constructor-based conversion
};
template<int a, int b> foo<a, b>::operator bar<a> const () { return bar<a>(); }
template<int a> void f(bar<a> x, bar<a> y) { }
int main() {
bar<1> x;
foo<1, 2> y;
f(x, y);
}
对此,gcc 4.8.3说:
template argument deduction/substitution failed: ‘foo<1, 2>’ is not derived from ‘bar<a>’
意图是f
的第二个参数通过我控制的一些代码从foo<1,2>
转换为bar<1>
。但显然,模板化转换构造函数和非模板化转换运算符都不适用于此情况。我可以使用任何成语来完成这项工作吗?
答案 0 :(得分:5)
模板参数推导需要精确匹配(如{x 3}}中的Xeo指出,如果需要,将应用单个标准转换序列(第4章),并且不考虑用户定义的转换。因此,它无法将第二个参数中的模板参数a
推断为f()
(类型为foo<1,2>
)。解决此问题的一种方法是将第二个参数类型转换为非推导的上下文。然后{@ 1}}将仅从第一个参数中推导出来,并且您的代码将被编译。
a
答案 1 :(得分:2)
当您对两个或多个参数执行模板参数推导时,两个参数必须完全匹配,通过限定转换或通过基类转换(14.8.2.1p4 [temp.deduct.call] )。
您可以使用类型转换来抑制对一个参数的参数推断:
template<class T> struct identity { using type = T; };
template<class T> using identity_t = typename identity<T>::type;
template<int a> void f(bar<a> x, identity_t<bar<a>> y) { }