类型推导失败:将派生模板的shared_ptr转换为基本模板作为函数参数

时间:2018-12-08 03:40:34

标签: c++ templates shared-ptr

在这里,我声明了两个模板类:A和B,B从A派生:

template<typename T>
class A {
public:
    int a;
    T t;
};

template<typename T>
class B : public A<T> {
public:
    int b;
};

然后我创建一个shared_ptr<B<T>>并将其分配给shared_ptr<A<T>>,没关系:

auto b = std::make_shared<B<std::string>>();
std::shared_ptr<A<std::string>> a = b;

在这里,我声明了一个模板函数接受shared_ptr A<T>

template<typename T>
void proc(std::shared_ptr<A<T>> &a) {
    std::cout << a->a << std::endl;
}

它接受a作为参数,但拒绝b

proc<std::string>(a); // OK
proc<std::string>(b); // template argument deduction/substitution failed
                      // cannot convert 'b' (type 'std::shared_ptr<B<std::__cxx11::basic_string<char> > >') to type 'std::shared_ptr<A<std::__cxx11::basic_string<char> > >&'

我将g ++用作带有-std = c ++ 11的编译器。

此错误给我带来了很多问题,该如何解决呢?

2 个答案:

答案 0 :(得分:3)

鉴于proc<std::string>(b);b需要转换为std::shared_ptr<A<std::string>>。这意味着将构造一个临时std::shared_ptr<A<std::string>>,然后将其传递给proc。参数类型proc是对非常量的左值引用,即std::shared_ptr<A<T>> &,它不能绑定到临时变量。

您可以将参数类型更改为const的左值引用,这可以绑定到临时变量。例如

template<typename T>
void proc(const std::shared_ptr<A<T>> &a) {
//        ^^^^^
    std::cout << a->a << std::endl;
}

答案 1 :(得分:2)

首先,您创建一个shared_ptr,名称为:

auto b = std::make_shared<B<std::string>>();

类型为std::shared_ptr<B<std::string>>,并且

std::shared_ptr<A<std::string>> a = b;

类型为std::shared_ptr<A<std::string>> ...

但是,在功能参数中,您具有:

void proc(std::shared_ptr<A<T>> &a)

仅指向 A shared_ptr,而不是 B ,因此显而易见 B < / strong>不会成为 A ...


解决方案是从函数定义中删除a lvalue 引用,例如:

void proc(std::shared_ptr<A<T>> a)

因此,它没有引用 A ,并且可以在函数调用期间将 B 轻松转换为 A ...


编辑::添加了说明...

说明:

还记得指针吗?来自 C ... ,它们具有与引用相同的功能:

// Compilable both in C and C++...
int add(int a, int b, int * more_than_3) {
    int const result = a + b;
    if (result > 3)
        *more_than_3 = 1;
    return result;
}

是的,这些将在C语言中实现伪返回类型的功能。

// Compilable both in C and C++...
int main(void) {
    int more_3;
    int const res = add(2, 3, &more_3);
    printf("Sum of 2 + 3 is %i\n", res);
    if (more_3)
        printf("Given two numbers' sum is more than 3");
}

这里,传递了一个额外的参数,该参数使用 address of一个变量引用也做同样的事情,它们与引用它们的变量共享地址。 ...

记住,引用和指针存储其中另一个变量的地址 ...

这可能就是为什么他们使 运算符(&)的地址也充当 C ++ 中的引用的原因。 ..


也不需要,但是@songyuanyao在此处发布的答案有效,因为:

void proc(std::shared_ptr<A<T>> const &a)

使用常量引用,是常量表达式引用,而不是变量,因此它没有它们是否不匹配(AB