2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 "Проблема" с шаблонизированным оператором присваивания в C++
Сообщение22.12.2009, 00:09 
Заслуженный участник


26/07/09
1559
Алматы
Здравствуйте, я немного запутался с шаблонами и надеюсь на вашу помощь. :)

Собственно вопрос таков. Почему компилятор C++ "не видит" шаблонизированное определение оператора присваивания (вероятно, это более общая проблема, просто я с ней столкнулся именно при использовании оператора присваивания) и продолжает использовать присваивание по-умолчанию? Для демонстрации сего феномена предлагаю такой пример:

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>

class Circle {};

template <class Kind> struct Shape {};

template <>
struct Shape<Circle>
{
    template <class Kind>
    const Shape<Circle> &operator =
        (const Shape<Kind> &Object)
    {
        std::cout << "Assignment.";

        return *this;
    }

    /*
    **  const Shape<Circle> &operator =
    **      (const Shape<Circle> &Object)
    **  {
    **      return operator=<Circle>(Object);
    **  }
    */


};

int main()
{
    Shape<Circle> FirstObject, SecondObject;

    FirstObject=SecondObject;

    return 0;
}
 


Эта программка печатает слово "Assignment" (т.е., использует переопределенный оператор присваивания) только если раскомментировать закомментированный фрагмент кода (т.е., если "специализировать" оператор присваивания). Объясните пожалуйста, почему так происходит и что мешает компилятору сделать подстановку шаблонных параметров самостоятельно? Если не затруднит, укажите соответствующие пункты стандарта. Спасибо.

Post scriptum. Может быть это как-то связано с предсказанием бесконечных рекурсий при раскрытии шаблонов? Дело в том, что шаблонизированный оператор присваивания прекрасно работает без вспомогательной перегруженной версии если тип его аргумента отличен от класса, для которого этот оператор определен. Например, следующий код работает как надо (с выполнением переопределенного оператора присваивания и выводом слова "Assignment"):
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>
#include <list>

class Circle {};

template <class Kind> struct Shape {};

template <>
struct Shape<Circle>
{
    template <class Kind>
    const Shape<Circle> &operator =
        (const std::list<Kind> &Object)
    {
        std::cout << "Assignment.";

        return *this;
    }

};

int main()
{
    Shape<Circle> FirstObject;
    std::list<Circle> SecondObject;

    FirstObject=SecondObject;

    return 0;
}
 

 Профиль  
                  
 
 Re: "Проблема" с шаблонизированным оператором присваивания в C++
Сообщение22.12.2009, 03:00 
Заслуженный участник


04/05/09
4584
Это потому, что не-темплейтные функции имеют приоритет перед темплейтными.
А в данном случае есть неявный не-темплейтный оператор присваивания.
См. например:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>

class Circle {};

template <class Kind> struct Shape {};

template <>
struct Shape<Circle>
{
    void foo(int) {
        std::cout << "foo(int)\n";
    }
    template <class X> void foo(const X&) {
        std::cout << "foo<"<<typeid(X).name()<<">()\n";
    }
    template <class Kind>
    const Shape<Circle> &operator =
        (const Shape<Kind> &Object)
    {
        std::cout << "Assignment from Shape<"<<typeid(Kind).name()<<"\n";

        return *this;
    }

    /*
    **  const Shape<Circle> &operator =
    **      (const Shape<Circle> &Object)
    **  {
    **      return operator=<Circle>(Object);
    **  }
    */


};

int main()
{
    Shape<Circle> FirstObject, SecondObject;

    FirstObject=SecondObject;

    FirstObject.foo(1);
    FirstObject.foo('1');
    FirstObject.foo(SecondObject);

    return 0;
}
 

В первом случае вызовется не-темплейтный foo(), а в остальных - темплейтный.

 Профиль  
                  
 
 Re: "Проблема" с шаблонизированным оператором присваивания в C++
Сообщение28.12.2009, 16:33 
Заслуженный участник


26/07/09
1559
Алматы
2venco
Спасибо, разобрался. Доканают меня когда-нибудь все эти неявные ctor\dtor\etc. :) Кстати, даже сообщение об ошибке было, довольно информативное, но я его сразу не увидел среди сотен других. :)

Не знаете, в самом свеженьком стандарте наконец-то ввели для классов обещанный модификатор explicit, запрещающий компилятору создавать что-либо внутри класса втихаря?

 Профиль  
                  
 
 Re: "Проблема" с шаблонизированным оператором присваивания в C++
Сообщение28.12.2009, 17:02 
Заслуженный участник


04/05/09
4584
Насчёт explicit не знаю, но могу дать совет, как убрать неявные методы. Надо их объявить в private секции, но нигде не определить. Тогда на попытку их использования за пределами класса будет ругаться компилятор, а внутри класса, где есть доступ к private методам, будет ругаться линкер. Можно и во втором случае сделать так, чтобы ругался компилятор, но мне обычно хватало этого:
Используется синтаксис C++
class A {
public:
  ...
private:
  // hide implicit methods
  A(const A&);
  void operator=(const A&);
};
 

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 4 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group