错误:std::variant 的模板参数列表中的类型/值不匹配

error: type/value mismatch in template parameter list for std::variant

提问人:glades 提问时间:10/4/2022 更新时间:10/4/2022 访问量:224

问:

如果类是模板化的,则以下代码不起作用。所以我的猜测是我必须把说明符放在某物前面,但我真的不知道在哪里?我尝试将其放在变体定义中的state::base和state::error类型前面,但这不起作用。我把它放在哪里,为什么?some_classtemplate

演示

#include <variant>

template <typename T>
class some_class
{
    void do_something() {
        struct state {
            struct base{};
            struct error{};
        };

        std::variant<state::base, state::error> fsm{};
    }
};

int main() {}

错误

<source>:12:47: error: type/value mismatch at argument 1 in template parameter list for 'template<class ... _Types> class std::variant'
   12 |         std::variant<state::base, state::error> fsm{};
      |                                               ^
<source>:12:47: note:   expected a type, got 'some_class<T>::do_something()::state::base'
<source>:12:47: error: type/value mismatch at argument 1 in template parameter list for 'template<class ... _Types> class std::variant'
<source>:12:47: note:   expected a type, got 'some_class<T>::do_something()::state::error'
C++ 模板 C++20 依赖项名称

评论


答:

3赞 user17732522 10/4/2022 #1

编译器认为 和 是依赖的(基于模板参数),在这种情况下,它们需要前缀 with,以便在分析类模板定义时将它们视为类型。state::basestate::errortypename

然而,从直觉上看,这些名称/类型似乎不应该是依赖的。尽管对于封闭类模板的每个专用化,类型是不同的类型,但可以保证,对于封闭模板的每个实例化,该类型将始终在函数定义中命名和引用已知类型。这不能改变,例如通过显式或部分专业化。state::base

这似乎是一个悬而未决的CWG问题(CWG 2074)。该标准目前没有说这些名称是依赖的。仅当本地类包含依赖类型时,它们才会具有依赖性(请参阅 [temp.dep.type]/9.5),但在您的情况下,它们不会这样做。尽管如此,似乎一些编译器认为这些类型是依赖的。

因此,您的解决方案是为它们添加前缀,即使根据标准可能不需要或不打算这样做。typename

评论

0赞 glades 10/4/2022
谢谢你的解释。我认为用户会从范围的角度思考,而在这种情况下编译器不会这样做。我同意你的看法,这不是很直观。typename 解决了这个问题。