Здравствуйте, atanasyan, Вы писали:
Если взять твой пример без шаблонов, то не скомпилится
потому что компилятор не знает что взять или конструктор
S2(const S1 &);
или оператор преобразования
operator S2() const;
тоже самое в твоём примере, если мы специализируем
operator S2<0> () const
то есть я веду к этому
в случае как есть, он выбирает конструктор потому что
он как бы "специализирует" шаблонный оператор преобразования
в принципе ты можешь запретить конструктор преобразования explicit-ом
Здравствуйте, 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)).