簡體   English   中英

在 class 上下文中使用時,前向聲明與就地前向聲明的工作方式不同

[英]Forward declarations don't work the same as in-place forward declarations when used in class context

我正在探索 C++ 實例化/聲明順序的奧秘。 這是我遇到的一個有趣的點:

這編譯:

#include <cstddef>
#include <variant>
#include <array>

template <size_t V>
struct container
{
    // THIS COMPILES
    struct array;
    using val = std::variant<std::monostate, int, array>;

    // THIS DOESNT
    // using val = std::variant<std::monostate, int, struct array>;

    struct proxy : val
    {
        using val::variant;
    };

    struct array { };
};

int main()
{
    container<10> ctr;
}

但是當您選擇就地聲明時,它突然停止工作( Demo ):

#include <cstddef>
#include <variant>
#include <array>

template <size_t V>
struct container
{
    // THIS COMPILES
    // struct array;
    // using val = std::variant<std::monostate, int, array>;

    // THIS DOESNT
    using val = std::variant<std::monostate, int, struct array>;

    struct proxy : val
    {
        using val::variant;
    };

    struct array { };
};

int main()
{

    container<10> ctr;
}

這是我得到的錯誤:

/opt/compiler-explorer/gcc-trunk-20220729/include/c++/13.0.0/type_traits:1012:52: error: static assertion failed: template argument must be a complete class or an unbounded array
 1012 |       static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
      | 

有人可以確切地解釋為什么會發生這種情況嗎? 有什么區別?

編輯:在某些情況下,您可以在模板參數列表中聲明一個類型:

#include <cstddef>
#include <variant>
#include <array>
#include <cstdio>

void foo(std::initializer_list<struct array>);

struct array
{
    array(int a) : a_{a} {}
    void print() {
        printf("%d\n", a_);
    }
    int a_;
};

void foo(std::initializer_list<struct array> init) {
    for (auto a : init) {
        a.print();
    }
    printf(".. it works\n");
}

int main()
{
    foo({1,2,3});
}

我不知道這適用於何時何地。

表格聲明

類鍵屬性說明符序列(選擇)標識符;

(其中class-key表示structclassunion ),在聲明出現的 scope 中聲明標識符[dcl.type.elab]/2 )。 這意味着在您的第一個代碼片段中, array被前向聲明為container class 模板的成員 class,您可以稍后在同一個 scope 中定義它。

當諸如struct array之類的詳細類型說明符作為某個更大的聲明或表達式的組件出現時, [dcl.type.elab]/3適用。 首先,編譯器查找名稱array ,忽略任何非類型( [basic.lookup.elab]/1 )。 如果它沒有找到任何東西,那么它將在“最近的封閉命名空間或塊范圍”中前向聲明array 因此,您稍后定義為嵌套 class 的struct array是不同的 class,而您之前稱為struct array的那個沒有定義。

暫無
暫無

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

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