简体   繁体   English

如何解决错误:嵌套名称说明符中的变量模板 ID“复杂类型”

[英]How can I resolve Error: variable template-id 'complex type' in nested-name-specifier

First, let's define the problem.首先,让我们定义问题。 We have a lot of class types in a larger project.在一个较大的项目中,我们有很多 class 类型。 A bunch of these types are code-gened by a tool we don't control the output for.一堆这些类型是由我们不控制 output 的工具生成的。 This means we can't control their inheritance chain, and their implementations may be very complex.这意味着我们无法控制它们的 inheritance 链,它们的实现可能非常复杂。 There is also existing tooling for rolling out these types intelligently using macros to build complex structures like complex switch case statements, and other repetitive implementations where templates just won't cut it.还有现有的工具可以使用宏智能地推出这些类型,以构建复杂的结构,例如复杂的 switch case 语句,以及模板无法解决的其他重复实现。 BUT I want some extra resiliency and safety of the type system wherever possible.但我希望尽可能地增加类型系统的弹性和安全性。 Thus I also want to be able to utilize TypeLists, and type_traits with static assertions to restrict certain interfaces with clear, readable error messages.因此,我还希望能够利用 TypeLists 和带有 static 断言的 type_traits 来限制具有清晰可读的错误消息的某些接口。 However, I am having a lot of trouble writing the code that groups these types into clusters, and I don't understand the error, which is mentioned in the title.但是,我在编写将这些类型分组为集群的代码时遇到了很多麻烦,而且我不理解标题中提到的错误。 I am giving this context in case I am running up against an obvious XY problem, but this has seemed the most promising path so far that I have found.我给出这个上下文以防我遇到一个明显的 XY 问题,但这似乎是迄今为止我发现的最有希望的路径。

Here's a simplified version of the code so far, I commented out certain includes so that you can just copy paste this as one block for testing, but left them as comments so you can get an idea of how this should link in a real example.到目前为止,这是代码的简化版本,我注释掉了某些包含,以便您可以将其复制粘贴为一个块进行测试,但将它们保留为注释,以便您了解在真实示例中应该如何链接。 I also excluded header guards for brevity, but assume the headers would have standard header guards:为简洁起见,我还排除了 header 防护装置,但假设标题将具有标准 header 防护装置:

    // AStruct.hpp
    // special group of 'A' structs (assume these are complex types and we can't control their inheritance chain)
    struct A0{};
    struct A1{};
    struct A2{};
    struct A3{};
    struct A4{};
    struct A5{};
    struct A6{};
    struct A7{};
    struct A8{};
    struct A9{};
    
    // BStruct.hpp
    // special group of 'B' structs (assume these are complex types and we can't control their inheritance chain)
    struct B0{};
    struct B1{};
    struct B2{};
    struct B3{};
    struct B4{};
    struct B5{};
    struct B6{};
    struct B7{};
    struct B8{};
    struct B9{};
    
    // TypeList.hpp
    #include <type_traits>
    
    template<typename ... Types>
    struct TypeList;
    
    template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail> struct OneOf;
    
    template<template <typename T, typename U> typename Evaluator, typename Term, typename Head> struct OneOf<Evaluator, Term, TypeList<Head> >
    {
        using value = std::bool_constant<Evaluator<Term, Head>::value>;
    };
    template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail> struct OneOf<Evaluator, Term, TypeList<Head, Tail...> >
    {
        using value = std::bool_constant<Evaluator<Term, Head>::value || OneOf<Evaluator, Term, TypeList<Tail...> >::value>;
    };
    
    template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail >
    inline constexpr bool OneOfV = OneOf<Evaluator, Term, TypeList<Head, Tail...> >::value;
    
    // AStructUtils.hpp
    // #include TypeList.hpp
    // #include AStruct.hpp
    
    // This is setup as a macro so that other macros can consume it in addition
    // to templates with TypeList
    #define A_STRUCT_TYPES \
    A0, \
    A1, \
    A2, \
    A3, \
    A4, \
    A5, \
    A6, \
    A7, \
    A8, \
    A9
    
    template<typename AStruct>
    using AStructTypes = TypeList <A_STRUCT_TYPES>;
    
    template< typename AStruct >
    inline constexpr bool IsAStructV = OneOfV<std::is_same, AStruct, AStructTypes >::value;
    
    // BStructUtils.hpp
    // #include TypeList.hpp
    // #include BStruct.hpp
    
    // This is setup as a macro so that other macros can consume it in addition
    // to templates with TypeList
    #define B_STRUCT_TYPES \
    B0, \
    B1, \
    B2, \
    B3, \
    B4, \
    B5, \
    B6, \
    B7, \
    B8, \
    B9
    
    template<typename BStruct>
    using BStructTypes = TypeList <B_STRUCT_TYPES>;
    
    template< typename BStruct >
    inline constexpr bool IsBStructV = OneOfV<std::is_same, BStruct, BStructTypes >::value;
    
    // Driver main.cpp includes
    // #include AStructUtils.hpp
    // #include BStructUtils.hpp
    #include <string>
    #include <iostream>
    
    int main()
    {
        std::string buffer;
        buffer.append( "A4 is a AStruct type: " + std::to_string( IsAStructV<A4> ) + "\n" ); // 1
        buffer.append( "B4 is a AStruct type: " + std::to_string( IsAStructV<B4> ) + "\n" ); // 0
        buffer.append( "A4 is a BStruct type: " + std::to_string( IsBStructV<A4> ) + "\n" ); // 0
        buffer.append( "B4 is a BStruct type: " + std::to_string( IsBStructV<B4> ) + "\n" ); // 1
        std::cout << buffer << std::flush;
    }

And here's the full error:这是完整的错误:

:68:36: error: variable template-id 'OneOfV struct std::is_same, AStruct, template using AStructTypes = TypeList >' in nested-name-specifier :68:36: 错误:变量模板 id 'OneOfV struct std::is_same, AStruct, template using AStructTypes = TypeList >' in nested-name-specifier

Here's the example in GodBolt: https://godbolt.org/z/Mber5YToY这是 GodBolt 中的示例: https://godbolt.org/z/Mber5YToY

It's a bit unusual to alias a type as value .将类型别名为value有点不寻常。 Instead, I recommend you declare it as a static member so that you can directly extract it using a variable template.相反,我建议您将其声明为 static 成员,以便您可以使用变量模板直接提取它。

template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail> struct OneOf;

template<template <typename T, typename U> typename Evaluator, typename Term, typename Head> struct OneOf<Evaluator, Term, TypeList<Head> >
{
    static inline constexpr bool value = std::bool_constant<Evaluator<Term, Head>::value>::value;
};
template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail> struct OneOf<Evaluator, Term, TypeList<Head, Tail...> >
{
    static inline constexpr bool value = Evaluator<Term, Head>::value || OneOf<Evaluator, Term, TypeList<Tail...> >::value;
};

The template parameters of variable template OneOfV should be the exact same as Oneof in your case.在您的情况下,变量模板OneOfV的模板参数应该与Oneof完全相同。

template<template <typename T, typename U> typename Evaluator, typename Term, typename Head, typename ... Tail >
inline constexpr bool OneOfV = OneOf<Evaluator, Term, Head, Tail...>::value;

Otherwise, IsAStructV<A4> will expand to OneOf<std::same_as, A4, TypeList<AStructTypes>>::value , of which the third parameter is expected to be AStructTypes .否则, IsAStructV<A4>将扩展为OneOf<std::same_as, A4, TypeList<AStructTypes>>::value ,其中第三个参数应为AStructTypes

Also, there's no reason for AStructTypes to be a template.此外, AStructTypes没有理由成为模板。 It's a determined type.这是一个确定的类型。 So is BStructTypes . BStructTypes也是如此。

using AStructTypes = TypeList <A_STRUCT_TYPES>;

Demo演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM