簡體   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