Локальные классы и шаблонные функции
От: Roman Odaisky Украина  
Дата: 09.09.06 14:36
Оценка:
На этом форуме периодически заявляют о том, что один из недостатков Ц++ — отсутствие локальных функций. Мало помощи, мол, и от локальных классов — для использования их в шаблонных функциях требуется соответствующее (-ая? -ий?) 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);
},
и так даже работает.

Можно ли посмотреть на место в стандарте, регламентирующее поведение в такой ситуации? Так можно вообще?
До последнего не верил в пирамиду Лебедева.
Re: Локальные классы и шаблонные функции
От: dotidot Россия  
Дата: 09.09.06 22:49
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:


RO>
RO>int x[3] = { 0, 1, 2 };

RO>void f()
RO>{
RO>    struct Local
RO>    {
RO>        static int sq(int x)
RO>        {
RO>            return x * x;
RO>        }
RO>    };

RO>    std::transform(x, x + 3, x, &Local::sq);
RO>},
RO>
и так даже работает.


а вот так
Автор: dotidot
Дата: 31.08.06
не работает
Re: Локальные классы и шаблонные функции
От: MuTPu4  
Дата: 10.09.06 01:30
Оценка: 1 (1)
Здравствуйте, 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).
Существенно здесь то, что адрес функции без связывания передается только на стадии исполнения, на стадии же компиляции и компановки реализация имеет дело только с типами, обладающими внешним связыванием.
Re: Локальные классы и шаблонные функции
От: remark Россия http://www.1024cores.net/
Дата: 10.09.06 08:59
Оценка:
Здравствуйте, 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 не есть функция с внешним связыванием, поэтому не может быть параметром шаблона.


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: В догонку
От: remark Россия http://www.1024cores.net/
Дата: 10.09.06 09:16
Оценка:
Здравствуйте, 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.



R>


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Локальные классы и шаблонные функции
От: _DAle_ Беларусь  
Дата: 10.09.06 10:15
Оценка: 1 (1)
Здравствуйте, 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.
Re[2]: Локальные классы и шаблонные функции
От: Roman Odaisky Украина  
Дата: 10.09.06 11:58
Оценка:
Здравствуйте, remark, Вы писали:

RO>>Так можно вообще?


R>Нет, конечно.


Так подожди. Те участки стандарта вроде запрещают такое:

template <int (*F)(int)> class Z { . . . };

void foo()
{
    struct Local
    {
        static int sq(int x)
        {
            return x * x;
        }
    };

    Z<&Local::sq>().sayHello();
};

а у меня иначе, примерно так:

template <class F> class Z { . . . };
template <class F> Z<F> makeZ(F f) { return Z<F>(f); }

void foo()
{
    struct Local
    {
        static int sq(int x)
        {
            return x * x;
        }
    };

    makeZ(&Local::sq).sayHello(); // F = decltype(&Local::sq) = int (*)(int)
};

Вот выше говорят, что всё OK. Кому верить?

In strict mode, with -tused, Compile succeeded (but remember, the Comeau online compiler does not link).

До последнего не верил в пирамиду Лебедева.
Re[3]: Локальные классы и шаблонные функции
От: remark Россия http://www.1024cores.net/
Дата: 10.09.06 13:01
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, remark, Вы писали:


RO>>>Так можно вообще?


R>>Нет, конечно.


RO>Так подожди. Те участки стандарта вроде запрещают такое:


RO>Вот выше говорят, что всё OK. Кому верить?


... да... похоже я жёстко ступил...



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Локальные классы и шаблонные функции
От: MaximE Великобритания  
Дата: 10.09.06 18:57
Оценка: 12 (1)
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() по указателю не встраивает.

f():
.LFB611:
    .loc 1 5 0
    push    %ebp    #
.LCFI7:
    mov    %ebp, %esp    #,
.LCFI8:
    sub    %esp, 4    #,
.LCFI9:
.LBB8:
.LBB9:
    .loc 2 925 0
    mov    %eax, DWORD PTR x    # x, x
    mov    DWORD PTR [%esp], %eax    #, x
    call    f()::Local::sq(int)    #
    mov    DWORD PTR x, %eax    # x, tmp61
    mov    %eax, DWORD PTR x+4    # x, x
    mov    DWORD PTR [%esp], %eax    #, x
    call    f()::Local::sq(int)    #
    mov    DWORD PTR x+4, %eax    # x, tmp65
    mov    %eax, DWORD PTR x+8    # x, x
    mov    DWORD PTR [%esp], %eax    #, x
    call    f()::Local::sq(int)    #
    mov    DWORD PTR x+8, %eax    # x, tmp69
.LBE9:
.LBE8:
    .loc 1 16 0
    leave
    ret


Возможно такого же эффекта как здесь можно достичь, использовав локальный
namespace, ф-ция из которого гарантировано работает с шаблонами:

namespace { namespace Local {
int sq(int x)
{
     return x * x;
}
} }

void f()
{
     std::transform(x, x + 3, x, &Local::sq);
}


Символов побольше, строк на одну меньше, чем в оригинальном примере.

--
Maxim Yegorushkin

No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Posted via RSDN NNTP Server 2.0
Re[2]: Локальные классы и шаблонные функции
От: Roman Odaisky Украина  
Дата: 10.09.06 19:39
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Смысл использовать объекты-функторы (а не указатели на функции, как здесь) —

ME>эффективность. Вызов ф-ции по указателю не часто встраивается. g++ 4.1.1 -O3
ME>здесь цикл std::transform раскручивает, но вызов f() по указателю не встраивает.

Что ж, буду иметь в виду. VC 7.1 поступил аналогично g++ (я правильно делаю? /Oxb2?)

Вариант с функторами нравится меньше тем, что его приходится объявлять раньше по ходу и вне функции. (Пора сообразить скрипт и включить в подпись картинку «До C++09 осталось __ дней, __ часов, ...» )

И всё же: исходный вариант верен?
До последнего не верил в пирамиду Лебедева.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.