簡體   English   中英

了解在模板中定義的模板 (C++)

[英]Understanding templates defined inside templates (C++)

根據我的理解,以下兩個程序應該實際上是相同的,但是第二個程序編譯失敗。 請注意,在這個簡化的示例中,嵌套顯然是無用的,但在原始上下文中它是必要的。

版本 1:按預期工作

#include <iostream>                                                                                                                      
                                                                                                                                         
template<typename Value>                                                                                                                 
struct Anything {                                                                                                                        
    Value value;                                                                                                                         
};                                                                                                                                       
                                                                                                                                         
using A = const char *;                                                                                                                  
                                                                                                                                         
template<template<typename> class B>                                                                                                     
struct Inner {                                                                                                                           
    template<typename C>                                                                                                                 
    using type = B<C>;                                                                                                                   
};                                                                                                                                       
                                                                                                                                         
template<template<typename> class B>                                                                                                     
struct OuterBase {                                                                                                                       
    B<A> b;                                                                                                                              
                                                                                                                                         
    void                                                                                                                                 
    print() { std::cout << "b: " << b.value << std::endl; }                                                                              
};                                                                                                                                       
                                                                                                                                         
using Outer = OuterBase<Inner<Anything>::type>; // this version works                                                                                          
                                                                                                                                         
int                                                                                                                                      
main()                                                                                                                                   
{                                                                                                                                        
    Outer outer;                                                                                                                         
    outer.b.value = "foo";                                                                                                               
    outer.print();                                                                                                                       
                                                                                                                                         
    return 0;                                                                                                                            
} 

此版本中的編譯器錯誤是“期望一個模板,得到TypeBox<A>::Inner<Anything>::type ”。

版本 2:因編譯錯誤而失敗

#include <iostream>                                                                                                                      
                                                                                                                                         
template<typename Value>                                                                                                                 
struct Anything {                                                                                                                        
    Value value;                                                                                                                         
};                                                                                                                                       
                                                                                                                                         
template<typename A>                                                                                                                     
struct TypeBox {                                                                                                                         
    template<template<typename> class B>                                                                                                 
    struct Inner {                                                                                                                       
        template<typename C>                                                                                                             
        using type = B<C>;                                                                                                               
    };                                                                                                                                   
                                                                                                                                         
    template<template<typename> class B>                                                                                                 
    struct OuterBase {                                                                                                                   
        B<A> b;                                                                                                                          
                                                                                                                                         
        void                                                                                                                             
        print() { std::cout << "b: " << b.value << std::endl; }                                                                          
    };                                                                                                                                   
                                                                                                                                         
    using Outer = OuterBase<Inner<Anything>::type>; // compile error here                                                                                      
};                                                                                                                                       
                                                                                                                                         
int                                                                                                                                      
main()                                                                                                                                   
{                                                                                                                                        
    using Box = typename TypeBox<const char *>::Outer;                                                                                   
                                                                                                                                         
    Box box;                                                                                                                             
    box.b.value = "foo";                                                                                                                 
    box.print();                                                                                                                         
                                                                                                                                         
    return 0;                                                                                                                            
}    

我希望TypeBox結構在解析內部類型時是透明的,但根據gcc 12.2.1 ,它不是。 為什么不?

第二個示例的不同之處在於,編譯器無法在模板的定義點驗證Inner<Anything>::type確實是 class 模板或別名模板。 問題是Inner是一個嵌套的 class 模板,理論上你可以稍后為給定的模板參數部分或顯式地特化Inner ,以便type命名,例如類型。

因此編譯器傾向於要求您將template關鍵字放在模板名稱之前,在這種情況下 state 它確實是一個模板:

using Outer = OuterBase<Inner<Anything>::template type>;                                                                                      

我的理解是,盡管從技術上講,標准中沒有任何內容需要使用template ,但這並不完全清楚。 但是,該標准確實允許在此 position 中使用template關鍵字,但將在 C++23 中棄用此允許。 如果我沒記錯的話,即使對於以前的標准修訂版(作為缺陷報告),編譯器將來也應該允許在沒有template關鍵字的情況下這樣做。 執行此測試沒有任何意義。

另請參閱CWG 問題 1478和提議棄用P1787R6的論文。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM