隐式转换模板函数

时间:2017-07-11 05:33:47

标签: c++ templates

我有一个A类,其中实施了大多数操作。另外,我有另一个B类只包含A的成员。我希望A中的操作可以直接应用于B.所以我定义了一个转换操作。但是编译器抱怨"错误:没有匹配函数来调用' foo'"。隐式转换有什么问题?如何实现?感谢。

编辑:如果我将操作符重载添加到A并希望B直接使用它会怎么样?

template <typename T> struct B;

template <typename T>
struct A {
  A(const B<T>& b) {}    // Conversion from B to A, way 1
  friend void foo(const A&);
  // Addition
  friend A operator+(const A&, const A&);
};

template <typename T>
void foo(A<T>& a) {}

// Addition
template <typename T>
A<T> operator+(const A<T>& a1, const A<T>& a2) { return A<T>(); }

template <typename T>
struct B {
    B() {}
    A<T> a;
    operator A<T>() { return a; }   // Conversion from B to A, way 2
    // Addition
    B(const A<T>& a) : a(a) {}
};

int main()
{
    B<int> b;
    foo(b);
    auto bb = b+b;
}

2 个答案:

答案 0 :(得分:4)

您发布的代码存在两个主要问题。

  1. 编译器不会将B<int>转换为A<int>,以便将foo的模板参数推断为int。您必须帮助编译器。使用:

    foo<int>(B<int>());
    

    foo(static_cast<A<int>>(B<int>()));
    

    这只能解决问题的一半。

  2. 转换函数,无论编译器使用哪一个,都会产生临时对象。临时对象无法绑定到A<int>&。你必须使用

    template <typename T> void foo(A<T>) {}
    

    template <typename T> void foo(A<T> const&) {}
    
  3. 此外,friend中的A声明不正确。它声明非模板函数foofriend的{​​{1}}。如果您希望A<T>成为foo<T>的{​​{1}},则必须稍微更改一下代码。

    friend

    这是一个为我成功构建的完整程序。

    A<T>

答案 1 :(得分:0)

foo()将非const引用作为输入。 B的转换运算符返回临时A对象,并且temp不能绑定到非const引用参数。这就是你对foo()的调用无法编译的原因。

如果您要更改输入参数以取代const引用,它可以绑定到临时对象。但是,A有一个复制构造函数,它将B对象的const引用作为输入,因此您对foo()的调用可能仍然不明确。在构造临时B对象之后,编译器是应该使用A作为输入调用B复制构造函数,还是应该调用返回{B转换运算符的A转换运算符1}?我不确定标准是关于什么的,或者编译器如何实现它。