Здравствуйте, Николай Ивченков, Вы писали:
НИ>А поконкретнее?
А конкретнее, причем так, чтоб в лоб и наповал, в стандарте видимо нет. Ну посмотри например тот же 13.1:
13.1 Overloadable declarations [over.load]
. . .
[Note: this
restriction applies to explicit declarations in a scope, and between such declarations and declarations made
through a using-declaration (7.3.3). It does not apply to sets of functions fabricated as a result of name
lookup (e.g., because of using-directives) or overload resolution (e.g., for operator functions). ]
То есть "functions fabricated as a result of name lookup (e.g., because of using-directives)" тоже вносят вклад в перегрузку, только им разрешено например отличаться типом возвращаемого параметра.
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>Тогда такой вариант не должен компилироваться:
I>
ЮЖ>>namespace N {
ЮЖ>> void f() {}
ЮЖ>>};
ЮЖ>>using namespace N;
ЮЖ>>int f() { return 0;} // "перегруженная" функция отличается только возращаемым типом
ЮЖ>>int main(){ f(); }
I>Для того, чтобы этот вариант компилировался, в стандарте есть исключение:
Исключение из чего? Этот пример не подпадает под выделенное:
I>
I>13.1 Overloadable declarations [over.load]
I>1 Not all function declarations can be overloaded. Those that cannot be overloaded are specified here. A
I>program is ill-formed if it contains two such non-overloadable declarations in the same scope.
igna:
НИ>>А поконкретнее?
I>А конкретнее, причем так, чтоб в лоб и наповал, в стандарте видимо нет. Ну посмотри например тот же 13.1:
I>
I>13.1 Overloadable declarations [over.load]
I> . . .
I>[Note: this
I>restriction applies to explicit declarations in a scope, and between such declarations and declarations made
I>through a using-declaration (7.3.3). It does not apply to sets of functions fabricated as a result of name
I>lookup (e.g., because of using-directives) or overload resolution (e.g., for operator functions). ]
Посмотрел. Функции в разных scope не являются перегруженными, потому и конфликтов не возникает. Как с информативным, так и с нормативным текстом стандарта это очень даже хорошо согласуется.
igna:
ЮЖ>>Исключение из чего? Этот пример не подпадает под выделенное:
I>Правда? А на мой взгляд как раз подпадает.
Так scope-то разные.
"A namespace member name has namespace scope." (3.3.5/1)
Например, имя функции скрывает имя класса, объявленного в том же scope: "If a class or enumeration name and an object, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the object, function, or enumerator name is visible." (3.3.7/2). Для разных scope это не работает:
struct x {};
struct y {};
void x() {}
namespace
{
void y();
}
int main()
{
x(); // well-formed: x is function
y(); // ill-formed: y is ambiguous
}
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>Исключение из чего? Этот пример не подпадает под выделенное:
I>Правда? А на мой взгляд как раз подпадает. Если нет, не мог бы ты привести пример подпадающий под то самое выделенное?
void f();
int f();
int main(){}
PS: в том моем примере вызов 'f' в 'main' — лишний.
А из контекста-то зачем выпадать? Ты давай пример к которому относится "It does not apply to sets of functions fabricated as a result of name lookup (e.g., because of using-directives)".
Здравствуйте, Николай Ивченков, Вы писали:
НИ>Посмотрел. Функции в разных scope не являются перегруженными, потому и конфликтов не возникает. Как с информативным, так и с нормативным текстом стандарта это очень даже хорошо согласуется.
При таком понимании стандарта осталось только найти пример, к которому можно применить тот самый информативный текст.
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Юрий Жмеренецкий, Вы писали:
I>
ЮЖ>>void f();
ЮЖ>>int f();
ЮЖ>>int main(){}
I>
I>А из контекста-то зачем выпадать? Ты давай пример к которому относится "It does not apply to sets of functions fabricated as a result of name lookup (e.g., because of using-directives)".
Вон ты про что. Тогда твой пример:
namespace N {
void f(int) {}
};
using namespace N;
void f(char const*) {}
Только он не ill-formed не потому что "It does not apply to sets of functions fabricated..." а потому, что функции находятся в разных scope (о чем говорится в нормативном тексте выше). А уже из этого следует, что "It does not apply". Примечание можно вообще не рассматривать — ничего не изменится.
А вообще путаница, имхо из-за этого (13.1):
When two or more different declarations are specified for a single name in the same scope, that name is
said to be overloaded.
...
two declarations in the same scope that declare the same name but with different types are called overloaded declarations
Используя это определение, для выяснения наличия перегрузки достаточно найти все объявления в одном scope (и проверить несколько критериев). При этом непосредственно вызов не является необходимым.
Но:
function selection process is called overload resolution
Вот этот процесс выполняется при вызове функции (в выражении) и зависит от контекста вызова:
Overload resolution is a mechanism for selecting the best function to call given a list of expressions that are to be the arguments of the call and a set of candidate functions that can be called based on the context of the call.
Используя это определение, можно попробовать называть перегруженными функции которые участвуют в overload resolution (как процессе). Например, функция считаются перегруженной если set of candidate functions содержит как мимниму дву функции. Но в этом случае наличие факта перегрузки будет зависить от контекста вызова. Т.е. придется говорить "Эта функция перегружена в этом месте вызова, а в этом — нет" (в примечании к 1.9/18 используется оборот "overloaded in a valid context"). Это может показаться логичным, но в этом случае выяснение факта наличия перегрузки усложняется, да и наверняка всплывут какие-нибудь проблемы...
Здравствуйте, Юрий Жмеренецкий, Вы писали:
I>>Ты давай пример к которому относится "It does not apply to sets of functions fabricated as a result of name lookup (e.g., because of using-directives)".
ЮЖ>Вон ты про что. Тогда твой пример:
ЮЖ>Только он не ill-formed не потому что "It does not apply to sets of functions fabricated..."
Ну вот я как раз просил примера оправдывающего наличие этого "It does not apply to sets of functions fabricated as a result of name lookup (e.g., because of using-directives)" в стандарте.
ЮЖ>
Overload resolution is a mechanism for selecting the best function to call given a list of expressions that are to be the arguments of the call and a set of candidate functions that can be called based on the context of the call.
ЮЖ>Используя это определение, можно попробовать называть перегруженными функции которые участвуют в overload resolution (как процессе). Например, функция считаются перегруженной если set of candidate functions содержит как мимниму дву функции. Но в этом случае наличие факта перегрузки будет зависить от контекста вызова. Т.е. придется говорить "Эта функция перегружена в этом месте вызова, а в этом — нет" (в примечании к 1.9/18 используется оборот "overloaded in a valid context").
И именно такое понимание стандарта демонстрируют VC++ 9.0 и Comeau.
Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>Здравствуйте, igna, Вы писали:
I>>И именно такое понимание стандарта демонстрируют VC++ 9.0 и Comeau.
ЮЖ>Не только:
int f();
ЮЖ>void f();
ЮЖ>//...
ЮЖ>// C2556: 'void f(void)' : overloaded function differs only by return type from 'int f(void)'
Что "не только", не только VC++ 9.0 и Comeau или что? И кстати, ты вот этот пример видел?:
namespace N {
void f(int) {}
}
using namespace N;
void f(int) {}
int main()
{
f(1); // error C2668: 'f' : ambiguous call to overloaded function
}
Компилятор считает f overloaded, что вроде не совпадает с твоим мнением, так?
Здравствуйте, igna, Вы писали:
V>>Ты думаешь, что твой случай сильно от моего отличается? Или неймспейсы у нас уже не являются составляющим имени? Перегрузки никакой нет. N::f и ::f — это разные function group. Или тебя удивляет, что компилятор способен находить наиболее подходящую ф-ию из всех доступных в области видимости function groups?
I>Разве он находит ее не в соответствии с 13.3 Overload resolution стандарта?
Не только в соответствии с этим пунктом стандарта, ибо используются и другие пункты стандарта тоже.
А вообще, спор ведь терминологический. Попробую более четко сформировать в самом конце, а пока пара размышлизмов.
Сама терминология эта пошла еще с тех времен, когда не было неймспейсов, и была "честная" перегрузка одного и того же имени ф-ии. Но тогда проблемы терминологии не было, ибо эта проблема "перегрузки" в разных скопах нивелировалась сокрытием сигнатур, например как в наследнике переопределенная ф-ия скрывает одноименные ф-ии из базового класса, а не перегружает их, или как это происходит в локальном контексте:
void f(char*);
void g() {
extern void f(int);
f("asd"); // error, there is no f(char*) in this scope
}
А сейчас бардак, мягко говоря. Смотри, разве нестатический метода класса может перегрузить глобальную ф-ию? Ну вот исходя из здравого смысла? А внутри ф-ии члена? Этот процесс тоже описан в указанном тобой пункте стандарта при формировании candidate functions set.
Я тут уже пользовался терминологией из стандарта другого C-подобного языка, ИМХО там введен очень удачный термин function group, который есть семейство одноименных перегруженных ф-ий, а вовсе не аморфный candidate functions set как в стандарте С++. Ведь сейчас ситуация такова, что не можешь сказать, перегружает одна ф-ия другую или нет без контекста (и твои примеры именно это и демонстрируют). Просто получается так, что перегрузка ф-ий друг другом — это не св-во конкретной пары ф-ий, а внешнее, по отношению к ним св-во, определяемое контекстом вызова.
Все твои примеры можно свести было к этому:
// "сами по себе" ф-ии не перегружают друг друга namespace M { void f(int); }
namespace N { void f(char*); }
namespace {
using namespace N;
using namespace M;
// это определяется контекстом
f("asd");
}
Т.е. вывод такой, что однозначно о перегрузке набора ф-ий как неотъемлимом св-ве самого этого набора (что я имел ввиду все предыдущие посты) можно говорить лишь тогда, когда у них одинаковое полное имя (не символьно одинаковое, а семантически, ибо нейспейсы могут быть одноименны с типами) и одинаковая видимость и доступ. Все остальные случаи — суть наведенные эффекты конкретного контекста. Все.
Здравствуйте, vdimas, Вы писали:
V>Я тут уже пользовался терминологией из стандарта другого C-подобного языка, ИМХО там введен очень удачный термин function group, который есть семейство одноименных перегруженных ф-ий, а вовсе не аморфный candidate functions set как в стандарте С++.
Ты C# имеешь ввиду?
V>Ведь сейчас ситуация такова, что не можешь сказать, перегружает одна ф-ия другую или нет без контекста (и твои примеры именно это и демонстрируют).
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Юрий Жмеренецкий, Вы писали:
ЮЖ>>Здравствуйте, igna, Вы писали:
I>>>И именно такое понимание стандарта демонстрируют VC++ 9.0 и Comeau.
ЮЖ>>Не только: I>
int f();
ЮЖ>>void f();
ЮЖ>>//...
ЮЖ>>// C2556: 'void f(void)' : overloaded function differs only by return type from 'int f(void)'
ЮЖ>>Здесь контекст есть. А вот в отношении деклараций нельзя сказать перегрузка присутствует.
I>Ну так сообщение об ошибке компилятора (или сообщение компилятора об ошибке) верно?
Нет. "По стандарту" должно быть что-то вроде "overload resolution fails", с указанием того, что 'best viable' функция не уникальна (+ показать их список).