English 中文(简体)
C++模板级的超载[]操作员,总合/非最基本版本
原标题:Overloaded [] operator on template class in C++ with const / nonconst versions

Whew, 这是一项长期的工作。

这里我的问题。 我在C++和Im超载[]运营商的舱面上翻了一番模板。 我的版本既简明,也非最接近,不定的版本以提及方式返回,从而可以更改类别中的项目:

myobject[1] = myvalue;

直到我使用ean作为模板参数。 这里有一个充分的例子显示错误:

#include <string>
#include <vector>
using namespace std;

template <class T>
class MyClass
{
    private:
        vector<T> _items;

    public:

        void add(T item)
        {
            _items.push_back(item); 
        }

        const T operator[](int idx) const
        {
            return _items[idx];
        }

        T& operator[](int idx)
        {
            return _items[idx];
        }

};


int main(int argc, char** argv)
{
    MyClass<string> Test1;      //  Works
    Test1.add("hi");
    Test1.add("how are");
    Test1[1] = "you?";


    MyClass<int> Test2;         //  Also works
    Test2.add(1);
    Test2.add(2);
    Test2[1] = 3;


    MyClass<bool> Test3;        // Works up until...
    Test3.add(true);
    Test3.add(true);
    Test3[1] = false;           // ...this point. :(

    return 0;
}

错误是汇编错误,信息是:

error: invalid initialization of non-const reference of type ‘bool&’ from a temporary of type ‘std::_Bit_reference’

我读过并发现,STL使用了一些临时数据类型,但我不理解为什么它除包裹外一切照相。

在这方面的任何帮助都值得赞赏。

最佳回答

由于vector<bool>在STL中具有专门性,实际上不符合标准集装箱的要求。

Herb Sutter Negotiations about it more in a GOTW article:

问题回答

<代码>vector<bool>不是真正的集装箱。 你的法典实际上试图重新提及不允许的单一轨道。 您的集装箱改为deque。 我认为,你会采取你期望的行动。

vector<bool>”;与所有其他病媒一样没有实施,也不与这些病媒一样。 如果你的法典能够处理其许多特殊性,那么你就更不用说使用它了,而不是担心——这多半被认为是A Bad。 某些不思考的C++给我们带来启发 标准委员会成员。

对你的班级进行一些单一改动,应当加以确定。

template <class T>
class MyClass
{ 
    private:
        vector<T> _items;

    public:

        // This works better if you pass by const reference.
        // This allows the compiler to form temorary objects and pass them to the method.
        void add(T const& item)
        {
            _items.push_back(item);
        }

        // For the const version of operator[] you were returning by value.
        // Normally I would have returned by const ref.

        // In normal situations the result of operator[] is T& or T const&
        // But in the case of vector<bool> it is special 
        // (because apparently we want to pack a bool vector)

        // But technically the return type from vector is `reference` (not T&) 
        // so it you use that it should compensate for the odd behavior of vector<bool>
        // Of course const version is `const_reference`

        typename vector<T>::const_reference operator[](int idx) const
        {
            return _items[idx];
        }

        typename vector<T>::reference operator[](int idx)
        {
            return _items[idx];
        }
};  

正如其他答复指出的,在病媒加固、羊毛和大鼠的情况下,提供了优化空间分配的专门技术。

然而,如果你使用病媒:参考而不是T&,你仍然能够使你的代码有效。 事实上,使用集装箱是一种良好做法:在提及由STL集装箱持有的数据时参考。

T& operator[](int idx)

......

typename vector<T>::reference operator[](int idx)

当然,提交人也是参考的类型:

const T operator[](int idx) const

(删除无用额外拷贝)

typename vector<T>::const_reference operator[](int idx) const

之所以出现这一错误,是因为vector<bool>专门包装了在座标上和上储存的细菌值;bool>:operator[]回收某些代用法,使您能够获取价值。

我不认为解决办法是把与<条码>双轨制”;bool>:operator[]

如果您希望将<条码> 即作为基本类型加以保留,则我认为,可通过使用<条码>查询器和设计;MyBool>代替<条码>MyClass的发送<条码>。

它不妨这样做:

#include <string>
#include <vector>
using namespace std;

namespace detail
{
    struct FixForBool
    {
        bool value;
        FixForBool(bool b): value(b) {}
        operator bool&() { return value; }
        operator const bool& () const { return value; }
    };

    template <class T>
    struct FixForValueTypeSelection
    {
        typedef T type;
    };

    template <>
    struct FixForValueTypeSelection<bool>
    {
        typedef FixForBool type;
    };

}

template <class T>
class MyClass
{
    private:
        vector<typename detail::FixForValueTypeSelection<T>::type> _items;

    public:

        void add(T item)
        {
            _items.push_back(item);
        }

        const T operator[](int idx) const
        {
            return _items[idx];
        }

        T& operator[](int idx)
        {
            return _items[idx];
        }

};


int main(int argc, char** argv)
{
    MyClass<string> Test1;      //  Works
    Test1.add("hi");
    Test1.add("how are");
    Test1[1] = "you?";


    MyClass<int> Test2;         //  Also works
    Test2.add(1);
    Test2.add(2);
    Test2[1] = 3;


    MyClass<bool> Test3;        // Works up until...
    Test3.add(true);
    Test3.add(true);
    Test3[1] = false;           // ...this point. :(

    return 0;
}




相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签