3

如何使用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);
}

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);

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

candidate template ignored: invalid explicitly-specified argument for template parameter '_Tp' 

魔杖盒

更新询问如何解决而不是错误消息是什么意思。

4

2 回答 2

11

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 );
}

这通常可以用 C++14“通用 lambdas”来实现

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

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

    std::visit( [](auto v){std::cout << v;} , f );
}
于 2018-08-01T01:45:40.017 回答
3

gcc 8.1 的错误输出还包括解释:

<source>:10:29: error: the value of 'fi' is not usable in a constant expression
    auto ff = std::get<fi>(f);
                        ^
<source>:9:23: note: 'fi' was not initialized with a constant expression
   const std::size_t fi = f.index();

整数模板参数必须是常量表达式。 f不是常量表达式,因此对其非静态成员函数的调用不是常量表达式,因此fi不是。

您可以通过以下方式获得更好的错误消息:

constexpr std::size_t fi = f.index();

该代码get<fi>(f)只有f在也被声明为constexpr;时才能工作。但这只有在变体中的所有类型都有微不足道的析构函数时才有可能,但std::string事实并非如此。

于 2018-08-01T01:18:48.680 回答