[英]Forward declare using directive for recursive definitions
我有一個包含變體類型項目的數組,我想使用通用 std::array 迭代器對其進行迭代。 現在我想用我自己的 class array2
來管理陣列。 但是,該變體也可能包含一個類型為array2
的 object,它是使用變體本身實例化的,這意味着 val 已經作為模板參數需要。
從邏輯的角度來看,這個問題似乎是可以解決的:我沒有在array2
中使用val
類型的數據成員,這意味着 memory 的 val 布局可以在定義時固定。 但是,我必須轉發聲明 val 類型才能在 val 的定義中使用它。 我能以某種方式做到這一點嗎? 或者有沒有更慣用的方法來解決這個問題/解決方法?
我已經檢查了C++ 前向聲明使用指令,但它沒有回答我的問題,因為它不使用遞歸(這使它更容易)。
#include <variant>
#include <cstddef>
#include <array>
template <typename T, size_t V> struct array2;
template <size_t V>
using val = std::variant<std::monostate, int, array2<val, V>>;
template <typename T, size_t V>
struct array2
{
using iterator = typename std::array<T, V>::iterator;
iterator begin_; // array allocation not done in here
iterator end_;
};
int main() {}
產量:
<source>:9:54: error: 'val' was not declared in this scope
9 | using val = std::variant<std::monostate, int, array2<val, V>>;
更新:
請注意, array2
的大小不取決於 val 的定義,除了using
聲明確實要求std::array<val, V>
顯然是完整的。
不,你想要的是不可能的。
cppreference說關於類型別名的using
:
type-id [目標類型] 不能直接或間接引用標識符[正在定義的類型]。
在某些情況下問題是否“邏輯上”可解決並不重要,因為 C++ 是靜態類型語言,所有類型都必須在編譯時知道,而遞歸類型根本不可能,因為它們的類型解析過程永遠不會結尾。
前向聲明是完全不同的:使用前向聲明,您只是給出沒有定義的類型聲明,但該類型本身沒有問題,linker 將負責查找定義。 有關前向聲明的更多信息,請參閱此答案。
您需要像這樣簡單地擺脫遞歸,從 val 中獲取array2<val, V>
val
你可以使用這樣的東西來達到同樣的效果:
using val = std::variant<std::monostate, int>;
template <size_t V>
using valOrArray2Val = std::variant<val, array2<val, V>>;
我找到了解決方案。 如果您 typedef 一個 class 類型,您可以簡單地創建一個繼承 class 的代理類型,並受益於模板實例化僅在代理聲明已經完成時完成的事實:
#include <variant>
#include <cstddef>
#include <array>
template <typename T, size_t V> struct proxy;
template <typename T, size_t V>
struct proxy : std::variant<std::monostate, int, proxy<T, V>>
{
using iterator = typename std::array<T, V>::iterator;
iterator begin_; // array allocation not done in here
iterator end_;
};
int main() {}
注意:這僅在代理 class 中沒有代理數據成員時才有效(但這在這種情況下很明顯)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.