【问题标题】:c++ : std::visit not compilable under gccc++ : std::visit 在 gcc 下不可编译
【发布时间】:2021-07-19 13:21:42
【问题描述】:

这是我的代码,可以很好地为 clang 编译,但使用 gcc 失败

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

struct Id {
    void SetValue(const std::string& item)
    {
        value = item;
    }

    std::string value;
};

struct Number {
    void SetValue(const std::string& item)
    {
        value = std::stoi(item);
    }
    int value;
};


using TokenBase
    = std::variant<Number, Id>;

struct Token : TokenBase {
    using TokenBase::TokenBase;

    template <typename T>
    [[nodiscard]] bool Is() const {
        return std::holds_alternative<T>(*this);
    }

    template <typename T>
    [[nodiscard]] const T& As() const {
        return std::get<T>(*this);
    }

    template <typename T>
    [[nodiscard]] const T* TryAs() const {
        return std::get_if<T>(this);
    }
};

struct LexerTokenExtractor {
    const std::string& item_;

    void operator()(Number& item) const {
        item.SetValue(item_);
    }

    void operator()(Id& item) const {
        item.SetValue(item_);
    }
};


int main()
{
  const std::string string_token("x");
  Token id_token = Id();

  std::visit(LexerTokenExtractor{string_token}, id_token);

  std::cout << "ok" << std::endl;
}

这是日志:

required from here
/usr/include/c++/7/variant:97:29: error: incomplete type ‘std::variant_size<Token>’ used in nested name specifier
     inline constexpr size_t variant_size_v = variant_size<_Variant>::value;

/usr/include/c++/7/variant: In instantiation of ‘constexpr const auto std::__detail::__variant::__gen_vtable<void, LexerTokenExtractor&&, Token&>::_S_vtable’:
/usr/include/c++/7/variant:711:29:   required from ‘struct std::__detail::__variant::__gen_vtable<void, LexerTokenExtractor&&, Token&>’
/usr/include/c++/7/variant:1255:23:   required from ‘constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = LexerTokenExtractor; _Variants = {Token&}]’
1673947047/source.cpp:65:57:   required from here
/usr/include/c++/7/variant:711:49: error: ‘_S_apply’ was not declared in this scope
       static constexpr auto _S_vtable = _S_apply();

请告诉我这里可能出了什么问题

【问题讨论】:

  • 有什么解决办法吗?
  • 我不确定,但无论如何你可能想重新考虑你的设计;通常不建议从 std 类型继承。
  • @cigien 但是你自己的链接有这个:open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2162r2.html
  • @SergeyA 是的,没错 :) 这里很可能有一个有效的用例(我还没有阅读那篇论文)。但是如果代码不能编译,也许现在不继承(至少在修复错误之前),是一种合理的方法。

标签: c++ gcc std variant


【解决方案1】:

如 cmets 中所述,这是当前 GCC 版本中的一个已知错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90943

一个简单的解决方法是强制std::visit() 使用static_cast 直接对变体而不是子类进行操作。

std::visit(LexerTokenExtractor{string_token}, static_cast<TokenBase&>(id_token));

查看godbolt:https://gcc.godbolt.org/z/vMGfahq3z

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 2012-01-23
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    • 2018-08-09
    • 2021-05-24
    相关资源
    最近更新 更多