【问题标题】:Creating a custom comparable Tree-like data structor in C++在 C++ 中创建自定义可比较的树状数据结构
【发布时间】:2016-04-23 09:29:56
【问题描述】:

我有一个类型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 &lt; b) &amp;&amp; !(b &lt; a)
  • 比较的顺序并不真正相关,因为它看起来是一个严格的弱排序关系
  • 我希望 Type_Specifier 类型遵循 RAII 习语
  • Paramater_Specifier 类型仅用于 Type_Specifier 的子代,其他任何地方都没有
  • 我只希望使用 C++ 标准库

我曾考虑将Type_Specifier::parameters 设为std::vector&lt;Parameter_Specifier*&gt;,但随后我将不得不在Type_Specifier 中手动管理分配,这将导致明显的问题,因为Parameter_Specifier 在那里不完整。

【问题讨论】:

  • “但是我必须手动管理分配” 不,您可以使用std::vector&lt;std::unique_ptr&lt;Parameter_Specifier&gt;&gt;
  • @πάνταῥεῖ 根本没有帮助,它只是创建了一个新错误function "std::unique_ptr&lt;_Ty, _Dx&gt;::unique_ptr(const std::unique_ptr&lt;_Ty, _Dx&gt;::_Myt &amp;) [with _Ty=Parameter_Specifier, _Dx=std::default_delete&lt;Parameter_Specifier&gt;]" cannot be referenced -- it is a deleted function 没有修复任何错误,我也不知道如何编写一个表达式,给我一个(非空) std::vector&lt;std::unique_ptr&lt;Parameter_Specifier&gt;&gt;

标签: c++ c++11 tree operator-overloading incomplete-type


【解决方案1】:

关系运算符有问题。

1) 对于operator==(),您有两种选择:(a) 带有 one 参数的类/结构的方法(左侧参数 *this 是隐式的),可以'不是static,或者 (b) 带有 two 参数的外部函数(通常是friend)。您已经混合了这两种选择并创建了方法static。我强烈建议备选方案 (b):外部函数。所以(考虑到std::vector 有一个operator==()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&lt;() 也一样。此外,如果“left.tag &lt; rigth.tag”是false,我认为您应该验证这不是true,而是left.tag &gt; 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&lt;() 其他关系运算符很简单。对于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...好吧...将Type_Specifier更改为Parameter_Specifier

P.s.:对不起我的英语不好。

【讨论】:

    猜你喜欢
    • 2020-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 2017-06-01
    • 1970-01-01
    • 2013-12-20
    相关资源
    最近更新 更多