Отключить конструктор пересылки std :: option - PullRequest
1 голос
/ 24 мая 2019

Я расширил QDataStream с помощью оператора преобразования шаблонов, так что поток данных загружается из самого себя и конвертируется в любой поддерживаемый тип, например:

class ConvertibleQDataStream : public QDataStream
{
public:

    using QDataStream::QDataStream;

    template <class T>
    explicit operator T ()
    {
        T t;
        *this >> t;
        return t;
    }
};

И можно добавить поддержку типов, не поддерживаемых QDataStreamперегружая оператор >>, как таковой:

template <class T>
ConvertibleQDataStream&
operator >> (ConvertibleQDataStream& ds, std::vector<T>& v)
{
    //Called for std::vector's.
    return ds;
}

Идея состоит в том, чтобы иметь возможность создавать неконтролируемые классы, не являющиеся значениями по умолчанию, непосредственно из потока, например:

class Bar
{
public:

    Bar(ConvertibleQDataStream&);
};

class Foo
{
    int mInt;
    std::vector<double> mVector;
    Bar mBar;

public:

    Foo(ConvertibleQDataStream& ds) :
        mInt(ds),     //Calls operator >> for int and converts to int 
        mVector(ds),  //Calls operator >> for std::vector<T> and converts to std::vector<T>
        mBar(ds)      //Plain constructor call 
    {}
};

Это работаетотлично, за исключением случаев, когда членом является std::optional.Конструктор пересылки std::optional вызывается вместо оператора преобразования шаблона ConvertibleQDataStream:

template <class T>
ConvertibleQDataStream&
operator >> (ConvertibleQDataStream& ds, std::optional<T>& o)
{
    //Never called :(
    return ds;
}

class Qux
{
    std::optional<Bar> mOptional;

public:

    Foo(ConvertibleQDataStream& ds) :
        mOptional(ds) //calls Bar::Bar(ConvertibleQDataStream&) rather then operator >> for std::optional<T> due to forwarding c'tor.
    {}
};

Можно ли отключить конструктор пересылки std::optional?Или другой обходной путь для этого.

1 Ответ

2 голосов
/ 24 мая 2019

Это не проблема с опцией, это проблема в вашем проекте, где mOptional может быть создан из ConvertibleQDataStream.

Правила преобразования C ++ могут быть кошмаром , и в этом случае их, скорее всего, следует избегать, предоставляя явные операторы get.

class ConvertibleQDataStream : public QDataStream
{
public:
    using QDataStream::QDataStream;

    template <class T>
     T Get() const
    {
        T t;
        *this >> t;
        return t;
    }
};

class Qux
{
    std::optional<Bar> mOptional;

public:

    Foo(ConvertibleQDataStream& ds) :
        mOptional(ds.Get<std::optional<Bar>>())
    {}
};
...