Оный код успешно компилируется Comeau online и не компилируется VC8 sp1: 1>c:\program files (x86)\microsoft visual studio 8\vc\include\vector(693) : error C2259: 'Bar' : cannot instantiate abstract class 1> due to following members: 1> 'Bar::~Bar(void)' : is abstract 1> c:\projects\testsoap\testsoap\testoverload.cpp(12) : see declaration of 'Bar::~Bar' 1> c:\projects\testsoap\testsoap\testoverload.cpp(35) : see reference to class template instantiation 'std::vector<_Ty,_Ax>' being compiled 1> with 1> [ 1> _Ty=Bar, 1> _Ax=std::allocator<Bar> 1> ]
Т.е., очевидно, компилятор пытается инстанцировать template <class T> void foo(Bar &x, const std::vector<T> &t) для T==Bar, это, естественно, у него не получается, и тут вдруг вместо того, чтобы подставить template <class X> void foo(X &x, const std::vector<bool> &t) выдает ошибку компилляции. Если же лишить класс Bar чисто виртуальных функций, все странным образом собирается и работает, хотя vector<Bar> по прежнему не может быть инстанцирован — у Bar закрыты конструкторы и деструктор.
Собственно, вопросов два:
1) Я ничего не напутал и это действительно ошибка компилятора?
2) Как бы тут извратиться и все-таки суметь компилировать подобный код, с учетом того, что класс Bar и первый вариант функции foo (который template <class X> void foo(X &x, const std::vector<bool> &t) ) — сущности библиотечные и менять их крайне нежелательно.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
S>Т.е., очевидно, компилятор пытается инстанцировать template <class T> void foo(Bar &x, const std::vector<T> &t) для T==Bar, это, естественно, у него не получается, и тут вдруг вместо того, чтобы подставить template <class X> void foo(X &x, const std::vector<bool> &t) выдает ошибку компилляции. Если же лишить класс Bar чисто виртуальных функций, все странным образом собирается и работает, хотя vector<Bar> по прежнему не может быть инстанцирован — у Bar закрыты конструкторы и деструктор.
Во-первых, 14.7.1/5
If the overload resolution process can determine the correct function
to call without instantiating a class template definition, it is
unspecified whether that instantiation actually takes place. [Exam-
ple:
template <class T> struct S {
operator int();
};
void f(int);
void f(S<int>&);
void f(S<float>);
void g(S<int>& sr) {
f(sr); // instantiation of S<int> allowed but not required
// instantiation of S<float> allowed but not required
};
--end example]
Т.е. std::vector<Bar> может инстанциироваться в любом случае. Поведение unspecified. Поэтому разные компиляторы и компилируют по-разному.
Здравствуйте, remark, Вы писали:
R>Во-первых, 14.7.1/5 R>
R>If the overload resolution process can determine the correct function
R> to call without instantiating a class template definition, it is
R> unspecified whether that instantiation actually takes place. [Exam-
R> ple:
R> template <class T> struct S {
R> operator int();
R> };
R> void g(S<int>& sr) {
R> f(sr); // instantiation of S<int> allowed but not required
R> // instantiation of S<float> allowed but not required
R> };
R> --end example]
R>Т.е. std::vector<Bar> может инстанциироваться в любом случае. Поведение unspecified. Поэтому разные компиляторы и компилируют по-разному.
Во-вторых, что бы воспользоваться SFINAE тебе надо сделать так, что бы получающееся выражение было синтаксически некорректным, а не просто приводило бы когда-то к какой-то ошибке. Например, ошибке линковки или ран-тайм ошибке.
В твоём случае std::vector<Bar> синтаксически корректно, и при этом само это выражение не приводит к инстанциированию функций-членов std::vector<Bar>, в которых как раз уже и пытаются создать абстрактный класс. Поэтому на фазе поиска подходящих функций невозможно ничего определить.
Здравствуйте, remark, Вы писали:
R>Во-вторых, что бы воспользоваться SFINAE тебе надо сделать так, что бы получающееся выражение было синтаксически некорректным, а не просто приводило бы когда-то к какой-то ошибке. Например, ошибке линковки или ран-тайм ошибке. R>В твоём случае std::vector<Bar> синтаксически корректно, и при этом само это выражение не приводит к инстанциированию функций-членов std::vector<Bar>, в которых как раз уже и пытаются создать абстрактный класс. Поэтому на фазе поиска подходящих функций невозможно ничего определить.
В-третьих, тебе надо определиться, когда ты хочешь, что бы какая функция вызывалась.
Т.к. при таком определении как ты дал для некоторых комбинаций аргументов может вызываться и та и та функция. Как собственно ты в примере и привёл.
Вот, например, вариант, когда мы не хотим вызывать вторую функцию, когда второй параметр std::vector<bool>:
"remark" <38267@users.rsdn.ru> wrote in message news:2668540@news.rsdn.ru... > Здравствуйте, remark, Вы писали: > > R>Во-вторых, что бы воспользоваться SFINAE тебе надо сделать так, что бы получающееся выражение было синтаксически некорректным, а не просто приводило бы когда-то к какой-то ошибке. Например, ошибке линковки или ран-тайм ошибке. > R>В твоём случае std::vector<Bar> синтаксически корректно, и при этом само это выражение не приводит к инстанциированию функций-членов std::vector<Bar>, в которых как раз уже и пытаются создать абстрактный класс. Поэтому на фазе поиска подходящих функций невозможно ничего определить. > > > В-третьих, тебе надо определиться, когда ты хочешь, что бы какая функция вызывалась. > Т.к. при таком определении как ты дал для некоторых комбинаций аргументов может вызываться и та и та функция. Как собственно ты в примере и привёл. > > Вот, например, вариант, когда мы не хотим вызывать вторую функцию, когда второй параметр std::vector<bool>: > >
S>2) Как бы тут извратиться и все-таки суметь компилировать подобный код, с учетом того, что класс Bar и первый вариант функции foo (который template <class X> void foo(X &x, const std::vector<bool> &t) ) — сущности библиотечные и менять их крайне нежелательно.
S>Оный код успешно компилируется Comeau online и не компилируется VC8 sp1: S>Т.е., очевидно, компилятор пытается инстанцировать template <class T> void foo(Bar &x, const std::vector<T> &t) для T==Bar, это, естественно, у него не получается, и тут вдруг вместо того, чтобы подставить template <class X> void foo(X &x, const std::vector<bool> &t) выдает ошибку компилляции. Если же лишить класс Bar чисто виртуальных функций, все странным образом собирается и работает, хотя vector<Bar> по прежнему не может быть инстанцирован — у Bar закрыты конструкторы и деструктор.
Почему компилируется, когда закрыты члены — это понятно.
Шаблон vector<Bar> инстанцируется не весь, а лишь по мере необходимости. Нужен конструктор без параметров — сделаем. Не нужен — не сделаем.
При передаче по ссылке, очевидно, ничего больше не потребовалось. Поэтому private/protected не оказали влияние.
Почему компилятор ориентируется на наличие/отсутствие абстрактных функций у класса — не знаю. В принципе, должно было быть пофиг. (А если бы вместо std::vector был boost::shared_ptr, которому на абстракцию плевать?)
Скорее всего (имхо), комо и студия просто ткнули пальцем в небо и пошли разными путями. Комо угадал твои желания, а студия — нет.
S>Собственно, вопросов два: S>1) Я ничего не напутал и это действительно ошибка компилятора?
Ещё неизвестно, ошибка какого компилятора...
И что за ошибка...
S>2) Как бы тут извратиться и все-таки суметь компилировать подобный код, с учетом того, что класс Bar и первый вариант функции foo (который template <class X> void foo(X &x, const std::vector<bool> &t) ) — сущности библиотечные и менять их крайне нежелательно.
Как бы так извратиться, чтобы не смешивать указание и вывод параметров шаблона.
Вот, не смотря на содержание класса Bar, ты можешь определить, foo<Bar> относится к какому из шаблонов
— template<class X> void foo(X&, const vector<bool>&)
— template<class T> void foo(Bar&, const vector<T>&)
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[5]: SFINAE? compiler bug?
От:
Аноним
Дата:
24.09.07 13:24
Оценка:
Здравствуйте, Sergey, Вы писали:
1. если я не ошибаюсь SFINAE а тут точно тену если
2. в данной ситуации те boost::enable_if слишком шекарно.
3. и вопрос а почему у тебя деструктор чисто виртуальный?
леши класс абстракции и все скомпильится.(и protected за одно если конечно тебя это устраевает)
> Почему компилируется, когда закрыты члены — это понятно. > Шаблон vector<Bar> инстанцируется не весь, а лишь по мере необходимости. Нужен конструктор без параметров — сделаем. Не нужен — не сделаем. > При передаче по ссылке, очевидно, ничего больше не потребовалось. Поэтому private/protected не оказали влияние.
На самом деле, потребовалось. Я проверял, при комментировании "правильной" функции не компилируется даже при отсутствии чисто виртуальных функций в классе Bar.
> S>2) Как бы тут извратиться и все-таки суметь компилировать подобный код, с учетом того, что класс Bar и первый вариант функции foo (который template <class X> void foo(X &x, const std::vector<bool> &t) ) — сущности библиотечные и менять их крайне нежелательно. > > Как бы так извратиться, чтобы не смешивать указание и вывод параметров шаблона. > Вот, не смотря на содержание класса Bar, ты можешь определить, foo<Bar> относится к какому из шаблонов > — template<class X> void foo(X&, const vector<bool>&) > — template<class T> void foo(Bar&, const vector<T>&)
Ничего не понял
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
>> Как бы так извратиться, чтобы не смешивать указание и вывод параметров шаблона. >> Вот, не смотря на содержание класса Bar, ты можешь определить, foo<Bar> относится к какому из шаблонов >> — template<class X> void foo(X&, const vector<bool>&) >> — template<class T> void foo(Bar&, const vector<T>&)
S>Ничего не понял
Вот и я "ничего не понял". У тебя два разных шаблона функции foo, каждый из которых — с единственным параметром. К которому из них относится foo<Bar>?
Если бы параметры выводились компилятором из аргументов — никаких проблем, это обобщение ситуации с перегрузкой функций.
Это я к тому, что явная параметризация шаблона функции — зло. Оно имеет право на существование лишь в том случае, когда гарантируется, что шаблон единственный — раз уж язык позволяет объявлять множество разнородных функций и их шаблонов с одинаковым именем.
Вот с шаблонами классов такой фокус не прошёл бы. Там чётко: одно имя — один шаблон.
Хотя, если припахать нетривиальный поиск имён, то можно тоже довести компилятор и разработчика до истерики. (Особенно — разработчика).
>>> Как бы так извратиться, чтобы не смешивать указание и вывод параметров шаблона. >>> Вот, не смотря на содержание класса Bar, ты можешь определить, foo<Bar> относится к какому из шаблонов >>> — template<class X> void foo(X&, const vector<bool>&) >>> — template<class T> void foo(Bar&, const vector<T>&) > > S>Ничего не понял > > Вот и я "ничего не понял". У тебя два разных шаблона функции foo, каждый из которых — с единственным параметром. К которому из них относится foo<Bar>? > Если бы параметры выводились компилятором из аргументов — никаких проблем, это обобщение ситуации с перегрузкой функций.
Параметры в данном случае как раз и выводятся компилятором из аргументов.
> Это я к тому, что явная параметризация шаблона функции — зло.
Здесь она нужна только для того, чтобы отличить вызов шаблонной функции от вызова нешаблонной (в реальном коде они все шаблонные, но с разным числом параметров).
> Оно имеет право на существование лишь в том случае, когда гарантируется, что шаблон единственный — раз уж язык позволяет объявлять множество разнородных функций и их шаблонов с одинаковым именем.
На самом деле, мне просто деваться особо некуда. Надо перехватить вызов библиотечной функции, причем вызывается она тоже из библиотечного кода. Вообще-то это просто перегрузка boost::serialization::save для векторов. Хочется для некоторого типа архивов вызывать сначала мою функцию, из нее — библиотечную. Я не стал про это сразу писать, чтобы не отвлекать обсуждение в сторону буста и т.п.
> Вот с шаблонами классов такой фокус не прошёл бы. Там чётко: одно имя — один шаблон. > Хотя, если припахать нетривиальный поиск имён, то можно тоже довести компилятор и разработчика до истерики. (Особенно — разработчика).
С шаблонами классов хватило бы частичной специализации.
Posted via RSDN NNTP Server 2.1 beta
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Sergey, Вы писали:
S>С шаблонами классов хватило бы частичной специализации.
Дело в том, что частичная специализация шаблона класса — это ОДИН шаблон, состоящий из основной версии (наиболее общей) и множества специализаций.
А россыпь шаблонов перегруженных функций — это именно РОССЫПЬ.