访客访问变体并返回不同类型时出错

时间:2018-11-04 19:10:18

标签: c++ c++17

apply plugin: 'com.android.application'

android {
    compileSdkVersion 27
    defaultConfig {
        applicationId "***"
        minSdkVersion 19
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.1.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

有了这个我得到错误

#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,则编译正常。我在这里俯瞰什么? Here is a link to a godbolt

编辑:

我希望能够做data_output_two并获得双打,然后可能做std::visit(gen_visit, vec[0])并获得int。有可能吗?

1 个答案:

答案 0 :(得分:4)

访问返回单一类型。

您的代码要求它返回两种不同的类型。

它不能那样做。

现在,它返回的单个类型可能又是两种类型的变体。但是,大多数情况下,罐子是可以踢的。

{[](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] );