使用std :: get <index>访问std :: variant

Kar*_*rlM 2 c++ std variant c++17

如何使用v.index()then 访问变体成员std::get<index>(v)

当变体具有多个相同类型的条目时很有用.

以下不起作用.此代码不能在GCC或clang上编译

#include <iostream>
#include <variant>
#include <string>
#include <sstream>

typedef std::variant<int, int, std::string> foo;

std::string bar(const foo f) {

    const std::size_t fi = f.index();
    auto ff = std::get<fi>(f);

    std::ostringstream ss;      
    ss << "Index:" << fi << "   Value: " << ff;
    return ss.str();
}


int main()
{
    foo f( 0 );

    std::cout << bar(f);
}
Run Code Online (Sandbox Code Playgroud)

当然有很多版本的std :: get,所以错误信息很冗长.

gcc抱怨(对于每个版本的get <>)

prog.cc:10:29: error: the value of 'fi' is not usable in a constant expression
     auto ff = std::get<fi>(f);
                             ^
prog.cc:9:23: note: 'fi' was not initialized with a constant expression
     const std::size_t fi = f.index();
                       ^~
prog.cc:10:29: note: in template argument for type 'long unsigned int'
     auto ff = std::get<fi>(f);
Run Code Online (Sandbox Code Playgroud)

Clang抱怨(对于每个版本的get <>)(根据具体情况,重新_Tp或_Ip)

candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp' 
Run Code Online (Sandbox Code Playgroud)

Wandbox

更新以询问如何解决而不是错误消息的含义.

Dre*_*ann 7

std::get<>在请求编译时已知的索引时适用.

如果您需要在运行时对变量值进行操作,则惯用方法是使用访问者std::visit.

#include <iostream>
#include <variant>
#include <string>

struct output_visitor
{
    template< typename T >
    void operator() ( const T& value ) const
    {
        std::cout << value;
    }   
};

int main()
{
    std::variant<int, std::string> f( 0 );

    std::visit( output_visitor{}, f );
}
Run Code Online (Sandbox Code Playgroud)