簡體   English   中英

解決嵌套初始化列表數據結構的自引用

[英]Resolve self-referencing of nested initializer list datastructures

我正在嘗試解決這個難題:我正在使用可能包含原始類型的變體val以及可能再次包含變體的用戶定義容器。 如果沒有盒子包裝對象,這種自引用數據結構是不可能的。 這個包裝器對象包裝了容器arrayobj並提供了可確定的內存布局,因為它只持有指向這些容器的指針,而不是容器本身。

但現在問題來了:要使大括號括起來的初始化器列表語法與container一起使用,box 數據結構需要為一系列keyvalval提供給定的 std::initializer_list-constructors。 但是要定義 val 我需要知道所涉及的所有模板參數的完整類型,包括 box 對象。 但這又需要知道 val。 這將創建一個互惠定義集。 我該如何解決?

代碼( 編譯器資源管理器):

#include <string>
#include <variant>
#include <type_traits>

struct array;
struct obj;
struct keyval;

template <typename T>
struct box
{
    box(std::initializer_list<keyval> init) {

    }
    box(std::initializer_list<val> init) {

    }
    T* ptr_;
};

using val = std::variant<std::monostate, box<array>, box<obj>, int, bool>;

struct obj
{
    obj() {
    }
    obj(std::initializer_list<keyval> init) {
    }
};

struct array
{
    array() {
    }
    array(std::initializer_list<val> init) {
    }
};

struct keyval
{
    keyval() {
    }
    keyval(std::string str, val a) : key_{str}, val_{a} {
    }

    std::string key_;
    val val_ = std::monostate{};
};


struct container : public array, public obj
{
    using array::array;
    using obj::obj;
};

int main()
{
    container some_container = { {"first", true }, { "second", 1 }, { "third", {{"2first", 2}, {"2second", true}} } };
}

錯誤

<source>:15:31: error: 'val' was not declared in this scope
   15 |     box(std::initializer_list<val> init) {
      |                               ^~~
<source>:15:34: error: template argument 1 is invalid
   15 |     box(std::initializer_list<val> init) {
      |                                  ^
<source>: In function 'int main()':
<source>:59:117: error: could not convert '{{"first", true}, {"second", 1}, {"third", {{"2first", 2}, {"2second", true}}}}' from '<brace-enclosed initializer list>' to 'container'
   59 |     container some_container = { {"first", true }, { "second", 1 }, { "third", {{"2first", 2}, {"2second", true}} } };
      |                                                                                                                     ^
      |                                                                                                                     |
      |   
  1. 您必須在struct box的定義之前聲明using指令。 由於在val的聲明中引用了box ,因此您必須提出box的前向聲明。
template <typename T>
struct box;

using val = std::variant<std::monostate, box<array>, box<obj>, int, bool>;

template <typename T>
struct box {};
  1. std::variant不能直接從std::initializer_list ),這意味着
box<array> b{{"2first", 2},{"2second", true}}; // OK
val v1{b}; // OK
val v2{{"2first", 2},{"2second", true}}; // ERROR

這就是container構建失敗的原因。

一種簡單的解決方案是顯式提供類型。

container some_container = { {"first", true }, { "second", 1 }, { "third", box<array>{{"2first", 2}, {"2second", true}} } }; // note the box<array>
  1. 感謝@user17732522 對不完整類型事物的評論。 函數定義中的返回類型或參數類型必須是完整的,但聲明中不需要。 因此,在所有涉及的類都完成后,您需要將類內定義放在外面。

演示

暫無
暫無

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

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