циклическая зависимость в составной структуре с шаблонной специализацией

Кто-нибудь знает способ использовать специализацию шаблона с пользовательским классом, который используется в составной структуре?

Чтобы быть конкретным, я пишу программу для анализа / проверки документа XML, где данные XML хранятся в пользовательской составной древовидной структуре, которая построена с использованием моего class XMLNode структуры данных, как показано ниже.

Каждый объект XMLNode хранит дочерние узлы в своем std::unordered_set<XMLNode> children член, и я хочу использовать шаблонную специализацию std::hash структура, так что новые узлы могут быть вставлены с использованием специальной функции хеширования для объектов XMLNode. Это то, что я до сих пор:

    #include <string>
#include <unordered_map>
#include <forward_list>
#include <unordered_set>

class XMLNode {

private:

std::string element_name;
std::forward_list<std::string> content;
std::unordered_map<std::string, std::string> attributes;
**std::unordered_set<XMLNode> children;**

public:

// default constructor - sets member variables to empty containers and parent pointer to NULL.
XMLNode() : element_name(), content(), attributes(), children() {};

// copy constructor
XMLNode(const XMLNode & node) : element_name(node.element_name), content(node.content), attributes(node.attributes), children(node.children) {};

// destructor - members of the object are automatically emptied and freed when object passes out of scope.
~XMLNode() {};

// copy assignment operator - deep copy
XMLNode & operator = (const XMLNode & rhs)
{
element_name = rhs.element_name;
content = rhs.content;
attributes = rhs.attributes;
children = rhs.children;
return *this;
};

// compare two nodes are equal (have equal names and attributes)
bool operator ==(const XMLNode & comparison_node) const
{
return (element_name == comparison_node.element_name && attributes == comparison_node.attributes);
};

const std::string & get_name() const
{
return element_name;
};

};

namespace std
{
template<>
**struct hash<XMLNode>**
{
size_t
operator()(const XMLNode & obj) const
{
return hash<string>()(obj.get_name()); // implementation not finalised.
}
};
}

int main()
{
return 0;
}

Однако у компилятора есть проблема с этим, так как XMLNode класс зависит от std::hash<XMLNode (потому что std::unordered_set<XMLNode> children) а также std::hash<XMLNode требует class XMLNode быть определенным первым.

Чтобы быть конкретным, я получаю следующую ошибку при компиляции с VS 15.4.4: E1449 explicit specialization of class "std::hash<XMLNode>" must precede its first use (at line 575 of "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\type_traits")

Однако размещение std::hash<XMLNode> определение до XMLNode определение и вперед, объявляя XMLNode класс тоже не предлагает решения.

У кого-нибудь есть дизайнерское решение этой проблемы? Или это просто невозможно в C ++? Благодарю.

0

Решение

Просто объявите ваши классы сначала, определите второй. По этим направлениям (не проверено):

class XMLNode;

namespace std {
template<>
struct hash<XMLNode> {
size_t operator()(const XMLNode & obj) const;
};
}

class XMLNode {
/* actual definition here */
};

size_t std::hash<XMLNode>::operator()(const XMLNode & obj) const {
/* actual definition here */
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]