конвертация rvalue -> non-const reference.
От: _Winnie Россия C++.freerun
Дата: 06.10.05 20:04
Оценка:
Вот этот код компиляется в gcc --pedantic, icl /Za, cl /Za
Только icc выдает warning
test4.cpp(8): warning #597: "X::operator X &()" will not be called for implicit or explicit conversions

struct X
{
    operator X&()
    {
        return *this;
    }
};

X get_X()
{
    return X();
}

X &operator <<(/*note: non const reference!*/ X &x, int)
{
    return x;
}

void f()
{
    get_X() << 1 << 2 << 3;
}


Если этот operator X& убрать, то gcc ругается, что не может передать rvalue X по неконстантной ссылке.
test4.cpp:26: error: no match for 'operator<<' in 'get_X() << 1'
test4.cpp:20: note: candidates are: X& operator<<(X&, int)
Так что он нужен, и он вызывается. Что же icl плачется?

Теперь проблема в msvc.
Вот этот код компиляется в gcc/icc, но не компилируется в msvc8.0/7.1:


template <class OutIter>
struct text_out_t
{
    operator text_out_t&() 
    { 
        return *this; 
    } 
};

template <class OutIter>
text_out_t<OutIter>  &operator <<(text_out_t<OutIter>  &to, int)
{
    return to;
}

template <class OutIter>
text_out_t<OutIter> 
text_out()
{
    return text_out_t<OutIter> ();
}

int main()
{
    text_out<char *>() << 1 << 2 <<3;
}


Почему ic++ дает странный warning?
Корректно ли operator ThisType &() { return *this; } по стандарту?
Как заставить компилироваться это на msvc?

Я вижу только три выхода, и они мне все не нравяться —
1) сделать член у класса text_out_t вроде ref

text_out_t &ref()
{
  return *this;
}


нужен непонятный для пользователя tex_out().ref() << 1 << 2<< 3;

2)
Сделать все члены text_out_t как mutable, в operator << передавать по константной ссылке.
Не хочется этого делать, так как таких операторов много, писать по два лишних const (и, что более важно, не логичных) заставлять юзера тоже не хочу.

3) всегда передавать по значению.
Тоже не хочу, text_out_t может стать "тяжелым" классом с 5-10 членами.

Посоветуйте.
Правильно работающая программа — просто частный случай Undefined Behavior
Re: конвертация rvalue -> non-const reference.
От: _Winnie Россия C++.freerun
Дата: 06.10.05 20:25
Оценка:
Ага, como тоже не компиляет.
Как же удобней всего выйти из ситуации?
Правильно работающая программа — просто частный случай Undefined Behavior
Re: конвертация rvalue -> non-const reference.
От: Aznog Россия  
Дата: 06.10.05 20:38
Оценка:
Здравствуйте, _Winnie, Вы писали:
_W>...

Из стандарта:

12.3.2 Conversion functions
...
A conversion function is never used to convert a (possibly cv-qualified) object to the (possibly cv-qualified) same object type (or a reference to it), to a (possibly cv-qualified) base class of that type (or a reference to it), or to (possibly cv-qualified) void.

Т.е. operator X&() класса X вызываться не будет (об этом и предупреждает icc)
Re[2]: конвертация rvalue -> non-const reference.
От: _Winnie Россия C++.freerun
Дата: 07.10.05 05:15
Оценка:
Здравствуйте, _Winnie, Вы писали:
_W>Как же удобней всего выйти из ситуации?

Пока решил передавать по значению...
Правильно работающая программа — просто частный случай Undefined Behavior
Re: конвертация rvalue -> non-const reference.
От: Centaur Россия  
Дата: 07.10.05 15:13
Оценка:
Здравствуйте, _Winnie, Вы писали:

_W>3) всегда передавать по значению.

_W>Тоже не хочу, text_out_t может стать "тяжелым" классом с 5-10 членами.

Если объект тяжело копировать, можно над ним написать smart reference. Такой класс с одним указателем на настоящий объект, и куча форвардящих функций. Smart reference копировать легко.
Re[2]: конвертация rvalue -> non-const reference.
От: _Winnie Россия C++.freerun
Дата: 07.10.05 15:30
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Если объект тяжело копировать, можно над ним написать smart reference. Такой класс с одним указателем на настоящий объект, и куча форвардящих функций. Smart reference копировать легко.


Мне надо его возвращать из функций Не создавать же его на хипе из-за этого?

В связи с этим родился такой "шедевр":

struct persistent_format_options_t
{
    //pack field as possible, text_out_t often passed/returned by value.
    uint32_t m_zero_pad : 8;
    uint32_t m_precision : 8;
    uint32_t m_pos_sign : 2;
    uint32_t m_alternavive : 1; //not implemented yet
    uint32_t m_thousand_separator : 1;  //not implemented yet
        
    enum positive_sign_t { e_ps_none = 0 , e_ps_plus = 1, e_ps_space = 2};
    
    positive_sign_t get_positive_sign()
    {
        return positive_sign_t(m_pos_sign);
    }
    
    positive_sign_t set_positive_sign(positive_sign_t in_pos_sign)
    {
        m_pos_sign = in_pos_sign;
    }
    
    persistent_format_options_t()
        :m_zero_pad(0)
        ,m_precision(6)
        ,m_pos_sign(e_ps_none)
        ,m_alternavive(false)
        ,m_thousand_separator(false)
    {
    }
};


Если станет совсем невмоготу, придется делать все члены mutable, а все передачи по значению заменить на const ref
Правильно работающая программа — просто частный случай Undefined Behavior
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.