На этом форуме периодически заявляют о том, что один из недостатков Ц++ — отсутствие локальных функций. Мало помощи, мол, и от локальных классов — для использования их в шаблонных функциях требуется соответствующее (-ая? -ий?) linkage, т. е. приходится объявлять такие вспомогательные классы вне функции. Но я давно уже пишу вот так:
int x[3] = { 0, 1, 2 };
void f()
{
struct Local
{
static int sq(int x)
{
return x * x;
}
};
std::transform(x, x + 3, x, &Local::sq);
},
и так даже работает.
Можно ли посмотреть на место в стандарте, регламентирующее поведение в такой ситуации? Так можно вообще?
Здравствуйте, Roman Odaisky, Вы писали:
RO>Можно ли посмотреть на место в стандарте, регламентирующее поведение в такой ситуации? Так можно вообще?
Я думаю, что код является вполне корректным. Основные ограничения, накладываемые на типовые аргументы шаблона, перечислены в (14.3.1/2):
A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argumentfor a template type-parameter.
причем данные правила относится к diagnosable rules (1.4/1), т.е. при их нарушении реализация обязаны выдать диагностику (1.4/2).
В приведенном же примере, в результате вывода аргументов шаблона, параметр UnaryOperation получит значение int (*)(int), которое является составным (compound) типом, включающим только фундаментальрные типы. К сожалению, я не смог найти в стандарте прямого указания на то, что фундаментальные типя обладают внешним связыванием, однако на это намекает определение из (3.5/2).
Существенно здесь то, что адрес функции без связывания передается только на стадии исполнения, на стадии же компиляции и компановки реализация имеет дело только с типами, обладающими внешним связыванием.
Здравствуйте, Roman Odaisky, Вы писали:
RO>На этом форуме периодически заявляют о том, что один из недостатков Ц++ — отсутствие локальных функций. Мало помощи, мол, и от локальных классов — для использования их в шаблонных функциях требуется соответствующее (-ая? -ий?) linkage, т. е. приходится объявлять такие вспомогательные классы вне функции. Но я давно уже пишу вот так:
RO>Можно ли посмотреть на место в стандарте, регламентирующее поведение в такой ситуации? Так можно вообще?
Нет, конечно.
14.3.2/1
A template-argument for a non-type, non-template template-parameter shall be one of:
...
— the address of an object or function with external linkage
3.5/2
— When a name has external linkage, the entity it denotes can be referred to by names from scopes of
other translation units or from other scopes of the same translation unit.
Очевидно, что Local::sq не есть функция с внешним связыванием, поэтому не может быть параметром шаблона.
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Roman Odaisky, Вы писали:
RO>>На этом форуме периодически заявляют о том, что один из недостатков Ц++ — отсутствие локальных функций. Мало помощи, мол, и от локальных классов — для использования их в шаблонных функциях требуется соответствующее (-ая? -ий?) linkage, т. е. приходится объявлять такие вспомогательные классы вне функции. Но я давно уже пишу вот так:
RO>>Можно ли посмотреть на место в стандарте, регламентирующее поведение в такой ситуации? Так можно вообще?
R>Нет, конечно.
R>14.3.2/1 R>
R>A template-argument for a non-type, non-template template-parameter shall be one of:
R>...
R>— the address of an object or function with external linkage
R>3.5/2 R>
R>— When a name has external linkage, the entity it denotes can be referred to by names from scopes of
R>other translation units or from other scopes of the same translation unit.
R>
R>Очевидно, что Local::sq не есть функция с внешним связыванием, поэтому не может быть параметром шаблона.
В догонку 3.5/5
In addition, a member function, static data member, class or enumeration of class scope has external linkage
if the name of the class has external linkage.
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Roman Odaisky, Вы писали:
RO>>На этом форуме периодически заявляют о том, что один из недостатков Ц++ — отсутствие локальных функций. Мало помощи, мол, и от локальных классов — для использования их в шаблонных функциях требуется соответствующее (-ая? -ий?) linkage, т. е. приходится объявлять такие вспомогательные классы вне функции. Но я давно уже пишу вот так:
RO>>Можно ли посмотреть на место в стандарте, регламентирующее поведение в такой ситуации? Так можно вообще?
R>Нет, конечно.
R>14.3.2/1 R>
R>A template-argument for a non-type, non-template template-parameter shall be one of:
R>...
R>— the address of an object or function with external linkage
Параметр шаблона std::transform UnaryOperation является type-parameter.
Здравствуйте, Roman Odaisky, Вы писали:
RO>Здравствуйте, remark, Вы писали:
RO>>>Так можно вообще?
R>>Нет, конечно.
RO>Так подожди. Те участки стандарта вроде запрещают такое:
RO>Вот выше говорят, что всё OK. Кому верить?
Roman Odaisky wrote:
> На этом форуме периодически заявляют о том, что один из недостатков Ц++ > — отсутствие локальных функций. Мало помощи, мол, и от локальных классов > — для использования их в шаблонных функциях требуется соответствующее > (-ая? -ий?) linkage, т. е. приходится объявлять такие вспомогательные > классы вне функции. Но я давно уже пишу вот так: > >
int x[3] = { 0, 1, 2 };
>
> void f()
> {
> struct Local
> {
> static int sq(int x)
> {
> return x * x;
> }
> };
>
> std::transform(x, x + 3, x, &Local::sq);
> }
> > и так даже работает. > > Можно ли посмотреть на место в стандарте, регламентирующее поведение в > такой ситуации? Так можно вообще?
Смысл использовать объекты-функторы (а не указатели на функции, как здесь) —
эффективность. Вызов ф-ции по указателю не часто встраивается. g++ 4.1.1 -O3
здесь цикл std::transform раскручивает, но вызов f() по указателю не встраивает.
Здравствуйте, MaximE, Вы писали:
ME>Смысл использовать объекты-функторы (а не указатели на функции, как здесь) — ME>эффективность. Вызов ф-ции по указателю не часто встраивается. g++ 4.1.1 -O3 ME>здесь цикл std::transform раскручивает, но вызов f() по указателю не встраивает.
Что ж, буду иметь в виду. VC 7.1 поступил аналогично g++ (я правильно делаю? /Oxb2?)
Вариант с функторами нравится меньше тем, что его приходится объявлять раньше по ходу и вне функции. (Пора сообразить скрипт и включить в подпись картинку «До C++09 осталось __ дней, __ часов, ...» )