简体   繁体   English

重载类下标运算符以访问成员std :: vector对象的元素

[英]Overloading the class subscript operator to access elements of a member std::vector object

I am parsing a text based file to read variables from it. 我正在解析基于文本的文件以从中读取变量。 Existence of variables in the file is important, so I decided to write a template class which will hold both value of the variable ( Value ) and its existence flag ( Exists ). 文件中变量的存在很重要,所以我决定编写一个模板类,它将保存变量( Value )的Value和它的存在标志( Exists )。

template<class Type>
class MyVariable
{
    public:
        Type    Value;
        bool    Exists;
        MyVariable()
            : Exists(false), Value(Type())
        {
        }
        MyVariable(const Type & Value)
            : Exists(true), Value(Value)
        {
        }
        MyVariable(const Type && Value)
            : Exists(true), Value(std::move(Value))
        {
        }
        MyVariable(const Type & Value, bool Existance)
            : Exists(Existance), Value(Value)
        {
        }
        MyVariable(const Type && Value, bool Existance)
            : Exists(Existance), Value(std::move(Value))
        {
        }
        size_t size() const
        {
            return Value.size();
        }
        const MyVariable & operator=(const MyVariable &  Another)
        {
            Value   = Another.Value;
            Exists  = true;
        }
        const MyVariable & operator=(const MyVariable && Another)
        {
            Value   = std::move(Another.Value);
            Exists  = true;
        }
        const Type & operator[](size_t Index) const
        {
            return Value[Index];
        }
              Type & operator[](size_t Index)
        {
            return Value[Index];
        }
        operator const Type & () const
        {
            Value;
        }
        operator Type &()
        {
            Value;
        }
};

The stored variable type will occasionally be std::vector , so I overloaded the subscript operator operator[] to directly access the elements of the vector. 存储的变量类型偶尔会是std::vector ,所以我重载了下标运算operator[]来直接访问向量的元素。 So that I can make the Value and Exists members private. 这样我就可以将Value and Exists成员Exists私有。

I use this class like this in the code: 我在代码中使用这样的类:

const MyVariable<std::vector<int>> AVector({11, 22, 33, 44 ,55});
for (size_t i=0; i<AVector.size(); i++)
{
    std::wcout << L"Vector element #" << i << L" --> " << AVector.Value[i]  << std::endl;   // Works okay.
    std::wcout << L"Vector element #" << i << L" --> " << AVector[i]        << std::endl;   // Gives error.
}

I get the following error message: 我收到以下错误消息:

Error C2679 binary '<<' : no operator found which takes a right-hand operand of type 'const std::vector<int,std::allocator<_Ty>>' (or there is no acceptable conversion) 错误C2679二进制'<<' :找不到运算符,它接受类型'const std::vector<int,std::allocator<_Ty>>'的右手操作数(或者没有可接受的转换)

What am I doing wrong here? 我在这做错了什么?

const Type & operator[](size_t Index) const
{
    return Value[Index];
}

Type & operator[](size_t Index)
{
    return Value[Index];
}

Those return types are wrong; 那些返回类型是错误的; you are returning the contained type, not the container type. 您将返回包含的类型,而不是容器类型。 You can use decltype for this: 您可以使用decltype

auto operator[](size_t Index) const -> decltype(Value[Index]) 
{
    return Value[Index];
}

auto operator[](size_t Index) -> decltype(Value[Index]) 
{
    return Value[Index];
}

You're returning wrong type. 你输错了类型。

For const Type & operator[](size_t Index) const , Type is std::vector<int> , which means you're trying to return a vector , not the element of the vector . 对于const Type & operator[](size_t Index) constTypestd::vector<int> ,这意味着你试图返回一个vector ,而不是的元素vector

Try to change the type of return value to typename Type::value_type , such as 尝试将返回值的类型更改为typename Type::value_type ,例如

const typename Type::value_type& operator[](size_t Index) const

Your operator overload is declared 您的运算符重载已声明

const Type & operator[](size_t Index) const

But AVector is declared as 但是AVector被宣布为

const MyVariable<std::vector<int>>

So Type in your case is std::vector, and there is no << operator overload that accepts a std::vector for cout. 所以在你的情况下Type std :: vector,并且没有<< operator overload接受cout的std :: vector。

TartanLlama's and songyuanyao's answers are correct only when the contained variable type (ie; ValueType ) is std::vector . TartanLlama的songyuanyao的答案是正确的,只有当包含可变类型(即; ValueType )是std::vector If we attempt to store a fundamental data type (eg; int or float ), the compiler (MSVC14) gives the error below since there won't be any implicit subscript operator operator[] or value_type member type definition inside. 如果我们尝试存储基本数据类型(例如; intfloat ),编译器(MSVC14)会给出下面的错误,因为里面不会有任何隐式的下标操作operator[]value_type成员类型定义。

'InputFileVariable<bool,std::string>::value_type': is not a type name, static, or enumerator  
'InputFileVariable<int,std::string>::value_type': is not a type name, static, or enumerator  
'InputFileVariable<uintmax_t,std::string>::value_type': is not a type name, static, or enumerator  
'InputFileVariable<float,std::string>::value_type': is not a type name, static, or enumerator

I found the solution by using function templates. 我通过使用函数模板找到了解决方案。 I rewrote the subscript operators as templates, so that the compiler doesn't create the subscript member functions unless they are called. 我将下标运算符重写为模板,因此除非调用它们,否则编译器不会创建下标成员函数。 And since I call them only when the stored element is an std::vector , it doesn't cause any problem with fundamental types. 因为我只在存储的元素是std::vector时调用它们,所以它不会对基本类型造成任何问题。

My working final code is below. 我的工作最终代码如下。

#include <vector>
#include <string>

template<class ValueType, class KeyType = std::string>
class InputFileVariable
{
    public:
        const KeyType   Key;
        ValueType       Value;
        bool            Exists;
        InputFileVariable(KeyType && Key, ValueType && Value, bool Existance = false)
            :   Key     (std::forward<KeyType>  (Key)),
                Value   (std::forward<ValueType>(Value)),
                Exists  (Existance)
        {
        }
        size_t size() const
        {
            return Value.size();
        }
        const InputFileVariable & operator=(InputFileVariable && Another)
        {
            Key     = std::forward<InputFileVariable>(Another).Key;
            Value   = std::forward<InputFileVariable>(Another).Value;
            Exists  = true;
            return *this;
        }
        template <class ElementType = ValueType::value_type>
        const typename ElementType & operator[](size_t Index) const
        {
            return Value[Index];
        }
        template <class ElementType = ValueType::value_type>
        typename ElementType & operator[](size_t Index)
        {
            return Value[Index];
        }
        operator const ValueType & () const
        {
            return Value;
        }
        operator ValueType & ()
        {
            return Value;
        }
};

int wmain(int argc, wchar_t *argv[], wchar_t *envp[])
{
    // Used with "std::vector":
    InputFileVariable<std::vector<int>> MyVar1("MV1", {2, 4, 6, 8}, true);
    const size_t SIZE = MyVar1.size();
    std::cout << "Size = " << SIZE << std::endl;
    int Temp = MyVar1[1];
    MyVar1[1] = MyVar1[2];  // Here we call both the const and non-const operators.
    MyVar1[2] = Temp;
    for (size_t i=0; i<SIZE; i++)
    {
        std::cout << "MyVar1[" << i << "] = " << MyVar1[i] << std::endl;
    }

    // Used with "double":
    InputFileVariable<double> MyVar2("MV2", 3.14, true);
    std::cout << std::endl << "MyVar2    = " << MyVar2 << std::endl;

    std::cout << std::endl;
    _wsystem(L"timeout /t 60 /nobreak");
    return 0;
}

Output: 输出:

Size      = 4
MyVar1[0] = 2
MyVar1[1] = 6
MyVar1[2] = 4
MyVar1[3] = 8

MyVar2    = 3.14

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM