类型转换,“初始化”:无法从“ HtmlBuilder *”转换为“ HtmlElement”

时间:2018-07-05 20:45:23

标签: c++11 design-patterns builder fluent

我试图遵循一个教程,但是在为unique_ptr实现流利的生成器方面我也陷入了困境。 尽管知道这是类型转换的事情,但是在检查了文档之后,我找不到合适的修复程序。

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <memory>

using namespace std;

class HtmlBuilder;


struct HtmlElement
{
    string name;
    string text;

    vector<HtmlElement> elements;
    const size_t indent_size = 2;


    HtmlElement() {}



    HtmlElement(const string& name, const string& text) : name{ name }, text{ text }
    {

    }

    string str(int indent = 0) const // it is a const because it doesn't change the inner elements of htmlelement
    {
        ostringstream oss;
        string i(indent_size * indent, ' '); // repeating a character as many times as required. 

        oss << i << "<" << name << ">" << endl;


        if (text.size() > 0)
            oss << string(indent_size * (indent + 1), ' ') << text << endl;

        // recursive call
        for (const auto& e : elements)
            oss << e.str(indent + 1);

        oss << i << "</" << name << ">" << endl;
        return oss.str();
    }




    static HtmlBuilder build(string root_name);
    static unique_ptr<HtmlBuilder> create(string root_name);

};



struct HtmlBuilder
{

    HtmlBuilder(string root_name)
    {
        root.name = root_name;
    }




    HtmlElement root; // we can not do anything without root



    HtmlBuilder& add_child(string child_name, string child_text)
    {
        HtmlElement e{ child_name, child_text };


        root.elements.emplace_back(e);


        // it is a reference
        return *this;


    }


    HtmlBuilder* add_child2(string child_name, string child_text)
    {
        HtmlElement e{ child_name, child_text };


        // emplace_back will return a reference to element that was just created in the vector where as push_back does not return anything, so you could preform some chaining if you wanted
        root.elements.emplace_back(e);


        // it is a pointer
        return this;
    }

    string str() const {
        return root.str();
    }


    // let's you convert the builder to htmlelement.
    // automatic conversion.
    // it wil be converted only after the chaining has finished.
    operator HtmlElement() { return root; }





    /*B& operator= (const A& x) { return *this; }*/
    //operator unique_ptr<HtmlElement>() { 


    //  return root; 
    //}

};


// it had to be pasted here after definition of HtmlBuilder
HtmlBuilder HtmlElement::build(string root_name)
{

    // it will get automatically converted to a html element due to 
    // automatic conversion.
    return HtmlBuilder{ root_name };
}


unique_ptr<HtmlBuilder> HtmlElement::create(string root_name) {
    return make_unique<HtmlBuilder>(root_name);
}


// Basically we want to create builder from HtmlElement itself
// and be able to add childs as many as we want and at the end
// it will still return an HtmlElement due to automatic conversion
// in this way we hide builder completely

int main()
{

    HtmlBuilder builder{ "ul" };

    builder.add_child("li", "hello")
        .add_child("li", "world");

    //HtmlElement e = builder;


    // important: automatic conversion occurs only at the end, if the object itself is returned.
    HtmlElement e = HtmlElement::build("ul").add_child("li", "test").add_child("li", "test2");
    HtmlElement ee = HtmlElement::create("ul")->add_child2("li", "test")->add_child2("li", "test2");


    cout << e.str() << endl;





    getchar();
    return 0;
}

问题在于尝试使用此行:

HtmlElement::create("ul")->add_child2("li", "test")->add_child2("li", "test2");

它引发了如上所述的错误。它说不能从“ HtmlBuilder *”转换为“ HtmlElement”。尝试了几种解决方案,但是我是C ++的初学者,到目前为止还没有解决它。

1 个答案:

答案 0 :(得分:1)

您有一个operator()可以从HtmlBuilder转换为HtmlElement,而不能从HtmBuilder *转换为HtmlElement。那就是您的build()行和create()行之间的区别。

因此,您必须取消引用create()-> add_child2()行返回的指针。

尝试一下

HtmlElement ee = *(HtmlElement::create("ul")->add_child2("li", "test")->add_child2("li", "test2"));

Wandbox上运行

相关问题