2017-11-09 15 views
5

Tôi có một std::variant mà tôi muốn chuyển đổi sang một số khác std::variant có một tập hợp siêu loại. Có cách nào để làm điều đó hơn điều đó cho phép tôi chỉ đơn giản gán cái này cho cái kia không?Chuyển đổi std :: variant sang std khác :: biến thể với siêu tập hợp các loại

template <typename ToVariant, typename FromVariant> 
ToVariant ConvertVariant(const FromVariant& from) { 
    ToVariant to = std::visit([](auto&& arg) -> ToVariant {return arg ; }, from); 
    return to; 
} 

int main() 
{ 
    std::variant<int , double> a; 
    a = 5; 
    std::variant <std::string, double, int> b; 
    b = ConvertVariant<decltype(b),decltype(a)>(a); 
    return 0; 
} 

Tôi muốn có thể chỉ cần viết b = a để thực hiện chuyển đổi thay vì thực hiện quá trình thiết lập đúc phức tạp này. Không gây ô nhiễm không gian tên std.

Edit: Đơn giản chỉ cần viết b = a cung cấp cho các lỗi sau:

error C2679: binary '=': no operator found which takes a right-hand operand of type 'std::variant<int,double>' (or there is no acceptable conversion) 

note: while trying to match the argument list '(std::variant<std::string,int,double>, std::variant<int,double>)' 
+1

Nếu 'U' là vũ trụ của tất cả các loại, và P có U, không phải là P bằng U? Tôi gặp sự cố khi hiểu vấn đề bạn đang cố gắng giải quyết, có thể tôi là ngu ngốc: | – P0W

+0

Thử trực tiếp biên dịch 'b = a' để xem vấn đề. –

+0

Lỗi như sau: lỗi C2679: nhị phân '=': không tìm thấy toán tử nào có toán hạng bên phải của loại 'std :: variant ' (hoặc không có chuyển đổi được chấp nhận) lưu ý: khi cố gắng khớp với danh sách đối số '(std :: biến thể , std :: variant )' – Bomaz

Trả lời

3

Đây là một thực hiện tùy chọn thứ hai Yakk của:

template <class... Args> 
struct variant_cast_proxy 
{ 
    std::variant<Args...> v; 

    template <class... ToArgs> 
    operator std::variant<ToArgs...>() const 
    { 
     return std::visit([](auto&& arg) -> std::variant<ToArgs...> { return arg ; }, 
          v); 
    } 
}; 

template <class... Args> 
auto variant_cast(const std::variant<Args...>& v) -> variant_cast_proxy<Args...> 
{ 
    return {v}; 
} 

Bạn có thể muốn tinh chỉnh nó cho ngữ nghĩa chuyển tiếp.

Và như bạn có thể thấy việc sử dụng nó rất đơn giản:

std::variant<int, char> v1 = 24; 
std::variant<int, char, bool> v2; 

v2 = variant_cast(v1); 
0

Options:

  • Viết riêng variant loại của bạn, có thể kế thừa từ std::variant, mà thực hiện operator= và xây dựng theo cách bạn muốn . Một số công việc phải được thực hiện, bởi vì các nhà xây dựng của variant có thể thực hiện các thủ thuật SFINAE có thể không hoạt động đúng với loại biến thể của bạn; để kết thúc, bạn muốn thực hiện một số chuyển tiếp SFINAE cho chính biến thể thay vì khai báo using trần truồng.

  • Viết tốt hơn ConvertVariant không yêu cầu loại nguồn/đích được liệt kê. Bạn sẽ trả về loại mẫu trình trợ giúp chuyển đổi chứa biến thể nguồn có số operator std::variant<Ts...>()&& gọi một số thứ rất giống như ConvertVariant của bạn.

Các vấn đề liên quan