авто не удается определить правильный тип возвращаемого значения - PullRequest
7 голосов
/ 09 мая 2019

Я объявил функцию, которая возвращает auto тип shared_ptr параметризованного шаблонного класса.В моем случае компилятор жалуется на неполный тип, если я добавляю условие «else».С той же сигнатурой функции она отлично работает с одним условием.Любое элегантное решение, которое порадует компилятора.

auto getCustomerDataSource(ptree const &node){
   const auto dataSource = node.get<std::string>("<xmlattr>.Type");
   const auto sourceString = node.get<std::string>("SourceString");
   if (dataSource == "File") {
     return std::make_shared<CustomerData<CFileSource>>(sourceString);
   } else if (dataSource == "DataBase") {
     return std::make_shared<CustomerData<CDatabaseSource>>(sourceString);
   }
 }

Ответы [ 3 ]

14 голосов
/ 09 мая 2019

Ваш код нарушает следующее правило из стандарта C ++ [dcl.spec.auto.8] :

Если функция с объявленным типом возврата, который содержит тип заполнителя, имеет несколько неотбрасываемых return операторов , тип возврата выводится для каждого такого оператора return. Если выводимый тип не одинаков при каждом выводе, программа некорректна .


CFileSource & CDatabaseSource - два возможных алгоритма, по которым пользователь может выбрать один для построения CustomerData объекта.

Проблема в том, что вы пытаетесь использовать статический полиморфизм (шаблоны) для чего-то, что решается во время выполнения. Поэтому лучшим решением было бы предоставить ваши алгоритмы в виде полиморфных классов с общей базой. Затем вы можете сделать указатель на base, являющийся переменной-членом CustomerData, которая больше не должна быть шаблоном.

7 голосов
/ 09 мая 2019

Когда используется auto, выводимый тип возврата для функции должен быть одинаковым для всех возможных путей, которые может пройти программа. Здесь ваша функция имеет 3 различных возможных типа возврата:

  1. первый if тело выполнено: std::shared_ptr<CustomerData<CFileSource>>
  2. секунда if тело выполнено: std::shared_ptr<CustomerData<CDatabaseSoruce>>
  3. ни то, ни другое не выполнено: void

Это недействительно.

4 голосов
/ 09 мая 2019

CFileSource и CDatabaseSource - два возможных алгоритма, которые пользователь можно выбрать один для создания объекта CustomerData. Вы можете рассмотреть getCustomerDataSource как фабричный метод, который возвращает shared_ptr из CustomerData <> на основе переданного параметра.

Похоже, ваше недоразумение заключается в следующем: между двумя экземплярами одного и того же шаблона нет никакой связи, кроме того, что они являются экземплярами одного и того же шаблона.

Рассмотрим:

template<typename T>
struct Foo{};

??? bar(bool x) {
    if (x) return Foo<int>();
    return Foo<double>();
}

Нет типа, который вы могли бы поставить вместо ???, потому что Foo<int> и Foo<double> никак не связаны. Они являются воплощениями одного и того же tempalte, но это все.

Возможно, вы хотите что-то вроде этого:

struct Moo_base {};

template <typename T>
struct Moo : Foo_base {};

Потому что теперь Moo<int> и Moo<double> можно передавать через std::shared_ptr<Moo_base>.

...