ошибка вывода типа: shared_ptr производного шаблона в базовый шаблон в качестве аргумента функции - PullRequest
0 голосов
/ 08 декабря 2018

Здесь я объявил два шаблонных класса: 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 голосов
/ 08 декабря 2018

Прежде всего, вы создаете 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)

, который указывает только на shared_ptr из A , а не B так что очевидно , что B не станет A ...


Решением будет удаление lvalue ссылка a из определения функции, например:

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");
}

Здесь передается дополнительный аргумент, который принимает адрес переменную ( Ссылки также делают то же самое, они делят свой адрес с переменной, на которую они ссылаются ... )

Помните , хранилище ссылок и указателей адрес другой переменной внутри них ...

Это может быть причиной того, что они заставили адрес оператора (&) также действовать для ссылки в C ++ ...


Тоже, ненужный, но ответ, который был выложен здесь @ songyuanyao сработало, потому что:

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

использует постоянную ссылку , ссылку на постоянное выражение , а не переменную , так это дине имеет значения, если они не соответствуют (A и B)

0 голосов
/ 08 декабря 2018

Учитывая proc<std::string>(b);, b необходимо преобразовать в std::shared_ptr<A<std::string>>.Это означает, что временная std::shared_ptr<A<std::string>> будет построена и затем передана в proc.Тип параметра proc - это lvalue-ссылка на неконстантный, то есть std::shared_ptr<A<T>> &, который не может быть привязан к временным файлам.

Вы можете изменить тип параметра на lvalue-ссылку на const, которыйможет связываться с временными.например,

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