Выбор между оператором преобразования типа и конструктором
От: atanasyan  
Дата: 11.06.05 09:10
Оценка:
Не подскажет ли кто? Есть код:

struct S1;

template <int C>
struct S2
{
S2(const S1 &);
};

struct S1
{
template <int C>
operator S2<C> () const;
};

template <int C>
struct S3
{
template <class L>
S3(L, const S2<C> &);
} ;

S3<0> a(0, S1());

При создании объекта 'a' класса S3 компилятор выбирает вызов конструктора S2, которому передается экземпляр S1, а затем, получившийся объект класса S2 передается в конструктор S3. Меня это устраивает, но возникает вопрос: какое место стандарта С++ заставляет использовать такой путь, а не вызывать оператор преобразования типа для объекта класса S1? Это явно связано с положениями стандарта, т.к. разные компиляторы ведут себя одинаково.

Спасибо.
Re: Выбор между оператором преобразования типа и конструктор
От: A. Fedotov Украина  
Дата: 11.06.05 11:04
Оценка:
Здравствуйте, atanasyan, Вы писали:

Если взять твой пример без шаблонов, то не скомпилится
потому что компилятор не знает что взять или конструктор
S2(const S1 &);
или оператор преобразования
operator S2() const;

тоже самое в твоём примере, если мы специализируем
operator S2<0> () const

то есть я веду к этому
в случае как есть, он выбирает конструктор потому что
он как бы "специализирует" шаблонный оператор преобразования
в принципе ты можешь запретить конструктор преобразования explicit-ом
Re: Выбор между оператором преобразования типа и конструктор
От: Кодт Россия  
Дата: 13.06.05 08:38
Оценка:
Здравствуйте, atanasyan, Вы писали:

A>При создании объекта 'a' класса S3 компилятор выбирает вызов конструктора S2, которому передается экземпляр S1, а затем, получившийся объект класса S2 передается в конструктор S3. Меня это устраивает, но возникает вопрос: какое место стандарта С++ заставляет использовать такой путь, а не вызывать оператор преобразования типа для объекта класса S1? Это явно связано с положениями стандарта, т.к. разные компиляторы ведут себя одинаково.


Рассмотрим простой пример:
struct One;
struct Two;

struct One
{
  operator Two() const; // o1
// или
  template<class T> operator T() const; // o2
};

struct Two
{
  Two(const One&); // t1
// или
  template<class O> Two(const O&); // t2
};

void foo(const Two& t);

int main()
{
  foo(One());
}

Компилятор старается минимизировать количество действий — { подстановку шаблона, преобразование оператором, преобразование конструктором }.
Комбинации o1+t1 и o2+t2 приводят к тому, что оба способа имеют равный вес:
o1+t1 -> foo(Two(One)) и foo(One::operator Two)
o2+t2 -> foo(Two<One>(One)) и foo(One::operator T<Two>())
Комбинации o1+t2 и o2+t1 дают различные весы (в первом случае будет предпочтение One::operator Two(), во втором — Two(One)).
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.