Cannot find statement via implicit conversion in C ++

When writing a class to work in a shell around an object allocated by a bunch, I ran into a problem with implicit type conversion, which can be reduced to this simple example.

In the code below, the shell class manages the heaped object and is implicitly converted to a reference to this object. This allows you to pass a wrapper object as an argument to the write (...) function, since an implicit conversion occurs.

However, when trying to allow a call to the <<(...) operator, the compiler does not work if an explicit conversion is not performed (verified using the MSVC8.0, Intel 9.1, and gcc 4.2.1 compilers).

So, (1) why does implicit conversion fail in this case? (2) could this be related to the search argument dependent? and (3) is there anything that can be done to make this work without an explicit cast?

#include <fstream>

template <typename T>
class wrapper
{
    T* t;
  public:
    explicit wrapper(T * const p) : t(p) { }
    ~wrapper() { delete t; }
    operator T & () const { return *t; }
};

void write(std::ostream& os)
{
    os << "(1) Hello, world!\n";
}

int main()
{
    wrapper<std::ostream> file(new std::ofstream("test.txt"));

    write(file);
    static_cast<std::ostream&>( file ) << "(2) Hello, world!\n";
    // file << "(3) This line doesn't compile!\n";
}
+3
source share
5 answers

This fails because you are trying to resolve an operator of your class wrapper<T>that does not exist. If you want it to work without a cast, you could put together something like this:

template<typename X> wrapper<T> &operator <<(X &param) const {
    return t << param;
}

Unfortunately, I don't know how to resolve the return type at compile time. Fortunately, in most cases this is the same type as the object, including in this case c ostream.

EDIT: dash-tom-bang. wrapper<T> &.

+2

, , operator& . , , , : operator<<, const wrapper<std::ostream>.

+1

, . all < <. , ( ) , < .

, , , .

+1

. T f2(const bar<T>&) wrapper<bar<int> > bar<int>&.

template <typename T>
class wrapper
{
    T* t;
  public:
    explicit wrapper(T * const p) : t(p) { }
    ~wrapper() { delete t; }
    operator T & () const { return *t; }
};

class foo { };

template <typename T> class bar { };

void f1(const foo& s) { }
template <typename T> void f2(const bar<T>& s) { }
void f3(const bar<int>& s) { }

int main()
{
    wrapper<foo> s1(new foo());
    f1(s1);

    wrapper<bar<int> > s2(new bar<int>());
    //f2(s2); // FAILS
    f2<int>(s2); // OK
    f3(s2);
}

std::ostream typedef std::basic_ostream<..>, operator<<.

+1

... , ?

++ 03, char *:

template<class charT, class traits>
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&, const charT*);

. .

: .

The standard applies various restrictions on the applied transformations ... perhaps this will require an implicit conversion (your operator and casting to the base type) when you need to apply at most one.

0
source

Source: https://habr.com/ru/post/1703533/


All Articles