在相关模板类之间自动转换函数参数

时间:2014-07-29 16:46:02

标签: c++ templates c++11 type-conversion

假设我有一对相关的模板,我想自动将参数从一个函数转换为另一个函数。我怎样才能做到这一点?

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>。但显然,模板化转换构造函数和非模板化转换运算符都不适用于此情况。我可以使用任何成语来完成这项工作吗?

2 个答案:

答案 0 :(得分:5)

模板参数推导需要精确匹配(如{x 3}}中的Xeo指出,如果需要,将应用单个标准转换序列(第4章),并且不考虑用户定义的转换。因此,它无法将第二个参数中的模板参数a推断为f()(类型为foo<1,2>)。解决此问题的一种方法是将第二个参数类型转换为非推导的上下文。然后{@ 1}}将仅从第一个参数中推导出来,并且您的代码将被编译。

a

comments

答案 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) { }