繁体   English   中英

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

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

首先,让我们定义问题。 在一个较大的项目中,我们有很多 class 类型。 一堆这些类型是由我们不控制 output 的工具生成的。 这意味着我们无法控制它们的 inheritance 链,它们的实现可能非常复杂。 还有现有的工具可以使用宏智能地推出这些类型,以构建复杂的结构,例如复杂的 switch case 语句,以及模板无法解决的其他重复实现。 但我希望尽可能地增加类型系统的弹性和安全性。 因此,我还希望能够利用 TypeLists 和带有 static 断言的 type_traits 来限制具有清晰可读的错误消息的某些接口。 但是,我在编写将这些类型分组为集群的代码时遇到了很多麻烦,而且我不理解标题中提到的错误。 我给出这个上下文以防我遇到一个明显的 XY 问题,但这似乎是迄今为止我发现的最有希望的路径。

到目前为止,这是代码的简化版本,我注释掉了某些包含,以便您可以将其复制粘贴为一个块进行测试,但将它们保留为注释,以便您了解在真实示例中应该如何链接。 为简洁起见,我还排除了 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;
    }

这是完整的错误:

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

这是 GodBolt 中的示例: https://godbolt.org/z/Mber5YToY

将类型别名为value有点不寻常。 相反,我建议您将其声明为 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;
};

在您的情况下,变量模板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;

否则, IsAStructV<A4>将扩展为OneOf<std::same_as, A4, TypeList<AStructTypes>>::value ,其中第三个参数应为AStructTypes

此外, AStructTypes没有理由成为模板。 这是一个确定的类型。 BStructTypes也是如此。

using AStructTypes = TypeList <A_STRUCT_TYPES>;

演示

暂无
暂无

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

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