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

MvG*_*MvG 0 c++ templates type-conversion c++11

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

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);
}
Run Code Online (Sandbox Code Playgroud)

对此,gcc 4.8.3说:

template argument deduction/substitution failed: ‘foo<1, 2>’ is not derived from ‘bar<a>’
Run Code Online (Sandbox Code Playgroud)

意图将是,第二个参数f从被转换foo<1,2>bar<1>通过一些代码,I控制.但显然,模板化转换构造函数和非模板化转换运算符都不适用于此情况.我可以使用任何成语来完成这项工作吗?

Pra*_*ian 5

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

#include <functional>
#include <memory>

template<typename T>
struct identity
{
  using type = T;
};

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, typename identity<bar<a>>::type y) { }
//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int main() {
  bar<1> x;
  foo<1, 2> y;
  f(x, y);
}
Run Code Online (Sandbox Code Playgroud)

现场演示

  • "精确"只适用于只有一个标准转换序列适用的情况. (2认同)