Ошибка с посетителем варианта и возвратом разных типов - PullRequest
0 голосов
/ 04 ноября 2018
#include <iostream>
#include <vector>
#include <variant>

template<class... Ts> struct overload : Ts... { using Ts::operator()...; };
template<class... Ts> overload(Ts...) -> overload<Ts...>;

class data_output
{
public:
    double create_data() { return 1.57;}
};

class data_output_two
{
public:
    int create_data() { return 66;}
};



int main()
{
    using my_type = std::variant<data_output, data_output_two>;

    std::vector<my_type> data_vec;

    auto my_lambda = overload{[](data_output& d) {return d.create_data();},
                              [](data_output_two& d) {return d.create_data();}};

    data_vec.emplace_back(data_output{});
    data_vec.emplace_back(data_output_two{});

    std::cout << std::visit(my_lambda, data_vec[0]) << "\n";
}

С этим я получаю ошибку

/usr/include/c++/8.2.1/variant:836:43: error: 
invalid conversion from ‘std::__success_type<int>::type (*)(overload<main()::<lambda(data_output&)>, main()::<lambda(data_output_two&)> >&, std::variant<data_output, data_output_two>&)’ 
{aka ‘int (*)(overload<main()::<lambda(data_output&)>, main()::<lambda(data_output_two&)> >&, std::variant<data_output, data_output_two>&)’}
to ‘double (*)(overload<main()::<lambda(data_output&)>, main()::<lambda(data_output_two&)> >&, std::variant<data_output, data_output_two>&)’ [-fpermissive]
     { return _Array_type{&__visit_invoke}; }

Если я попытаюсь вернуть int как из data_output, так и data_output_two, то все будет хорошо. Что я здесь пропускаю? Вот ссылка на крестник

Edit:

Я хотел бы получить возможность сделать std::visit(gen_visit, vec[0]) и получить дубль, а затем, возможно, сделать std::visit(get_visit, vec[1]) и получить int. Это возможно?

1 Ответ

0 голосов
/ 04 ноября 2018

Визит возвращает один тип.

Ваш код просит вернуть два разных типа.

Он не может этого сделать.

Теперь единственный тип, который он возвращает, может, в свою очередь, быть вариантом над двумя типами. Но это в основном пинает банку в будущем.

{[](data_output& d)->std::variant<int,double> {return d.create_data();},
                          [](data_output_two& d)->std::variant<int, double> {return d.create_data();}};

с этим вам придется вернуться, чтобы напечатать:

std::visit( [](auto&&x){std::cout <<  x << "\n";}, std::visit(my_lambda, data_vec[0]) );

Теперь вы можете написать несколько метапрограммирований, чтобы определить правильный тип возвращаемого значения композитной перегрузки / посещения.

Но более просто выполнить обработку при первом посещении:

std::visit([&](auto&&x){ std::cout<<my_lambda(x)<<"\n";}, data_vec[0] );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...