在C++中创建自定义的类似树的数据结构器

Creating a custom comparable Tree-like data structor in C++

本文关键字:数据结构 创建 自定义 C++      更新时间:2023-10-16

我有一个类型struct Type_Specifier,我想表示一个可以比较的不可变树状结构。我有以下代码来说明我想要什么:

#include <vector>
struct Parameter_Specifier;
struct Type_Specifier
{
    explicit Type_Specifier(void* tag = nullptr, std::vector<Parameter_Specifier> parameters = {})
        : tag(tag), parameters(parameters) { }
    Type_Specifier(const Type_Specifier&) = default;
    Type_Specifier(Type_Specifier&&) = default;
    Type_Specifier& operator=(const Type_Specifier&) = default;
    Type_Specifier& operator=(Type_Specifier&&) = default;
    ~Type_Specifier() = default;
private:
    // Points to an arbitray memory location (whose lifetime is not managed by this type)
    void* tag;
    std::vector<Parameter_Specifier> parameters;
public:
    static bool operator ==(const Type_Specifier& left, const Type_Specifier& right)
    {
        if (left.tag != right.tag)
            return false;
        else if (left.parameters.size() != right.parameters.size())
            return false;
        else for (std::size_t i = 0; i < left.parameters.size(); i++)
        {
            if (!(left.parameters[i] == right.parameters[i]))
                return false;
        }
        return true;
    }
    static bool operator <(const Type_Specifier& left, const Type_Specifier& right)
    {
        if (left.tag < right.tag)
            return true;
        else if (left.parameters.size() < right.parameters.size())
            return true;
        else if (left.parameters.size() > right.parameters.size())
            return false;
        else for (std::size_t i = 0; i < left.parameters.size(); i++)
        {
            if (left.parameters[i] < right.parameters[i])
                return true;
            else if (right.parameters[i] < left.parameters[i])
                return false;
        }
        return false; // left == right
    }   
};
struct Parameter_Specifier
{
    explicit Parameter_Specifier(Type_Specifier type = Type_Specifier(), std::vector<char> value = {})
        : type(type), value(value) { }
    Parameter_Specifier(const Parameter_Specifier&) = default;
    Parameter_Specifier(Parameter_Specifier&&) = default;
    Parameter_Specifier& operator=(const Parameter_Specifier&) = default;
    Parameter_Specifier& operator=(Parameter_Specifier&&) = default;
    ~Parameter_Specifier() = default;
private:
    Type_Specifier type;
    // Arbitrary data (not a 'string' or sequence of 'characters')
    std::vector<char> value;
public:
    static bool operator ==(const Parameter_Specifier& left, const Parameter_Specifier& right)
    {
        if (!(left.type == right.type))
            return false;
        else if (left.value.size() != right.value.size())
            return false;
        else for (std::size_t i = 0; i < left.value.size(); i++)
        {
            if (left.value[i] != right.value[i])
                return false;
        }
        return true; // left == right
    }
    static bool operator <(const Parameter_Specifier& left, const Parameter_Specifier& right)
    {
        if (left.type < right.type)
            return true;
        else if (left.value.size() < right.value.size())
            return true;
        else if (left.value.size() > right.value.size())
            return false;
        else for (std::size_t i = 0; i < left.value.size(); i++)
        {
            if (left.value[i] < right.value[i])
                return true;
            else if (left.value[i] > right.value[i])
                return false;
        }
        return false; // left == right
    }
};

但是,它当然不会编译,可能是由于struct Parameter_Specifier不完整,并且运算符"<"和"=="未定义。

我的问题是这样的:如何修改上述类型使其编译和正常工作?(并且有效?

笔记:

  • 此类型的目的是用于双向映射结构,以便能够在struct Type_Specifierstd::size_t之间映射(即它需要同时是键类型和值类型)
  • 我将根据我对"=="和">"的定义定义其他比较运算符'!=',>,>="和"<=",为简洁起见,我在这里省略了它们
  • 我很确定a == b等同于!(a < b) && !(b < a)
  • 比较的顺序并不真正相关,因为它是一个严格的弱排序关系
  • 我希望Type_Specifier类型遵循 RAII 习语
  • Paramater_Specifier类型仅用于Type_Specifier子代,而不适用于其他任何地方
  • 我只喜欢使用C++标准库

我正在考虑将Type_Specifier::parameters作为std::vector<Parameter_Specifier*>但随后我将不得不手动管理分配,Type_Specifier,这会导致明显的问题,因为那里Parameter_Specifier不完整。

您在使用关系运算符时遇到问题。

1)对于operator==(),你有两个选择:(a)一个带有一个参数的类/结构的方法(左参数,*this,是隐式的),不能static,或者(b)一个具有两个参数的外部函数(通常friend)。您已将两种备选方案混合在一起,并使该方法static 。我强烈建议替代方案(b):外部功能。所以(算上有一个std::vectoroperator==()operator==() Type_Specifier可能是

friend bool operator== (const Type_Specifier & left,
                        const Type_Specifier & right)
 {
   return           ( left.tag == right.tag )
          && ( left.parameters == right.parameters );
 }

对于Parameter_Specifier可能是

friend bool operator== (const Parameter_Specifier & left,
                        const Parameter_Specifier & right)
 {
   return     ( left.type == right.type )
          && ( left.value == right.value );
 }

2)operator<()也是如此。此外,如果"left.tag < rigth.tag"是false,我认为你应该验证这不是true left.tag > right.tag。我对Type_Specifier的建议(但行为不同;谨慎)是

friend bool operator< (const Type_Specifier & left,
                       const Type_Specifier & right)
 {
   return    ( left.tag < right.tag )
          || (    ( left.tag == right.tag )
               && ( left.parameters < right.parameters ) );
 }  

对于Parameter_Specifier,我的建议(行为不同;谨慎)是

friend bool operator< (const Parameter_Specifier & left,
                       const Parameter_Specifier & right)
 {
   return    ( left.type < right.type )
          || (    (left.type == right.type )
               && (left.value < right.value ) );
 }

3)拥有operator==()operator<()他人的关系运算符很简单。对于Type_Specifier

friend bool operator!= (const Type_Specifier & left,
                        const Type_Specifier & right)
 { return ! (left == right); }
friend bool operator> (const Type_Specifier & left,
                       const Type_Specifier & right)
 { return (right < left); }
friend bool operator<= (const Type_Specifier & left,
                        const Type_Specifier & right)
 { return ! (right < left); }
friend bool operator>= (const Type_Specifier & left,
                        const Type_Specifier & right)
 { return ! (left < right); }

对于Parameter_Specifier...井。。。用Parameter_Specifier更改Type_Specifier

PS:对不起,我的英语不好。