Ограницения template type arguments
От: Аноним  
Дата: 01.02.10 17:09
Оценка:
Большинство компайлеров транслируют:
template<class T> struct A {
static T t; // 1
T *pt;      // 2
};

typedef int function();
A<function> a;  // ill-formed: would declare A<function>::t
                // as a static member function

Comeau ругает строку с // 1

14.3.1/3 If a declaration acquires a function type through a type dependent on a template-parameter and this causes a declaration that does not use the syntactic form of a function declarator to have function type, the program is ill-formed.


Проясните ситуацию в случае 2, должен ли компайлер разрешать, или нет? какие причины запрета в 1?
Re: Ограницения template type arguments
От: Кодт Россия  
Дата: 01.02.10 17:44
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Большинство компайлеров транслируют:

... до тех пор, пока ты не обратишься к соответствующему члену.

А>Comeau ругает строку с // 1

Ибо, как можно сделать переменную типа "функция"?
Вот переменную типа "указатель на функцию" — запросто.
Перекуём баги на фичи!
Re[2]: Ограницения template type arguments
От: Anonim547  
Дата: 01.02.10 19:10
Оценка: 34 (2)
Здравствуйте, Кодт, Вы писали:

К>Ибо, как можно сделать переменную типа "функция"?

К>Вот переменную типа "указатель на функцию" — запросто.

Насколько я успел понять, вопрос в трактовке 14.3.1/3. Стандарт не запрещает использовать тип таким образом:
typedef int function();

template<class T> struct A {
  // static T t;     // 1 - ill-formed, type dependent on a template-parameter
  static function t; // 1a - Ok
  T *pt;             // 2 - ???
  typedef T T2;      // 3 - ???
};

A<function> a; // комментарии выше указаны исключительно для данной специализации

здесь рассматривают похожий вопрос, в финале

I submitted a reduced version of the code to Comeau and asked them why it didn't compile. It turns out to be 14.3.1/3

Re[2]: Ограницения template type arguments
От: rg45 СССР  
Дата: 01.02.10 22:08
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Ибо, как можно сделать переменную типа "функция"?


Может, так, как здесь
Автор: rg45
Дата: 08.12.09
?
--
Справедливость выше закона. А человечность выше справедливости.
Re: Ограницения template type arguments
От: Юрий Жмеренецкий ICQ 380412032
Дата: 02.02.10 16:27
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Большинство компайлеров транслируют:

А>
А>template<class T> struct A {
А>static T t; // 1
А>T *pt;      // 2
А>};

А>typedef int function();
А>A<function> a;  // ill-formed: would declare A<function>::t
А>                // as a static member function
А>

А>Comeau ругает строку с // 1
А>

14.3.1/3 If a declaration acquires a function type through a type dependent on a template-parameter and this causes a declaration that does not use the syntactic form of a function declarator to have function type, the program is ill-formed.


А>Проясните ситуацию в случае 2, должен ли компайлер разрешать, или нет?


Должен, 'pt' имеет 'object type'.
Re[2]: Ограницения template type arguments
От: Anonim547  
Дата: 02.02.10 16:40
Оценка:
Здравствуйте, Юрий Жмеренецкий,

А что в случае c typedef T T2;? здесь
Автор: Anonim547
Дата: 01.02.10
Re[3]: Ограницения template type arguments
От: Юрий Жмеренецкий ICQ 380412032
Дата: 02.02.10 17:49
Оценка:
Здравствуйте, Anonim547, Вы писали:

A>Здравствуйте, Юрий Жмеренецкий,


A>А что в случае c typedef T T2;? здесь
Автор: Anonim547
Дата: 01.02.10


Также разрешено — вторая часть 14.3.1/3 не выполнится:

... and this causes a declaration ... to have function type


Единственный вид объявления (не учитывая 8.3.5/7), порождающее имя, которое имеет 'function type' — это 'function declaration' (декларация объектов-функций запрещена), 'typedef-declaration' создает только синоним для существующего типа.
Re[4]: Ограницения template type arguments
От: Anonim547  
Дата: 02.02.10 19:17
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Единственный вид объявления (не учитывая 8.3.5/7), порождающее имя, которое имеет 'function type' — это 'function declaration' (декларация объектов-функций запрещена), 'typedef-declaration' создает только синоним для существующего типа.


Если 'function type' не зависит от параметов шаблона, декларация функций не запрещена. Выглядит логичным, что проблема не в декларации функции, как таковой, а в зависимости типа от параметров шаблона.

Отсюда возникает вопрос: какова причина запрета на такой тип, нет ли в 14.3.1/3 неточностей, и не следует ли распространять причины запрета на другие случаи?

Поясню на примере, вопрос возник при анализе следующего:
void helper()
{
}

struct foo
{
    void bar() {}
};

template <class T, class F>
void check(F T::*)
{
    F* ptr = &helper; // error C2440: 'initializing' : cannot convert from 'void (__cdecl *)(void)' to 'void (*)(void)'
}

int main()
{
    check(&foo::bar);
    return 0;
}

Компайлер рассматривает calling convention как часть сигнатуры, стандартом это не определено, но как быть? В зависимости от установленной по умолчанию calling convention, VC выдает C2440 или ICE.
Re[5]: Ограницения template type arguments
От: Юрий Жмеренецкий ICQ 380412032
Дата: 02.02.10 20:45
Оценка: 6 (1)
Здравствуйте, Anonim547, Вы писали:

A>Здравствуйте, Юрий Жмеренецкий, Вы писали:


ЮЖ>>Единственный вид объявления (не учитывая 8.3.5/7), порождающее имя, которое имеет 'function type' — это 'function declaration' (декларация объектов-функций запрещена), 'typedef-declaration' создает только синоним для существующего типа.


A>Если 'function type' не зависит от параметов шаблона, декларация функций не запрещена. Выглядит логичным, что проблема не в декларации функции, как таковой, а в зависимости типа от параметров шаблона.


A>Отсюда возникает вопрос: какова причина запрета на такой тип, нет ли в 14.3.1/3 неточностей, и не следует ли распространять причины запрета на другие случаи?


Имхо, причина там одна — не дать возможность объявления объекта, который имеет 'function type'. В качестве альтернативы можно рассмотреть случай когда такая конструкция приводит к декларации функции, как и в случае c 8.3.5/7. Но это может привести к сюрпризам, т.к. инстанцирование шаблона функциональным типом и любым другим будет приводить к совершенно разным последствиям. Т.е. здесь как мне кажется имеет место "принцип наименьшего удивления": конструкция вида 'T f;' предствляет собой 'object declaration' и только ее, а попытка использования в качестве 'T' функционального типа приводит к ошибке. В случае же с независимыми типами, декларация функции в этом случае — осмысленный шаг со стороны программиста (и результат ни от чего не зависит).

Хотя вот еще интересный момент:

typedef void X();
void g(X)

template<class F>
struct A
{
  void f(F f);
};


В случае с 'g' ее фактический тип будет 'void(void(*)())' согласно 8.3.5/3. В случае c А<void()>::f логично было бы ожидать такого же поведения, но 14.3.1/3 вводит запрет на более ранней стадии:

8.3.5/3
The type of a function is determined using the following rules. The type of each parameter is determined from its own decl-specifier-seq and declarator. After determining the type of each parameter, any parameter of type “array of T” or “function returning T” is adjusted to be “pointer to T” or “pointer to function returning T,” respectively.

14.3.1/3
If a declaration acquires a function type through a type dependent on a template-parameter and this causes a declaration that does not use the syntactic form of a function declarator to have function type, the program is ill-formed.


A>Поясню на примере, вопрос возник при анализе следующего:

A>
A>void helper()
A>{
A>}

A>struct foo
A>{
A>    void bar() {}
A>};

A>template <class T, class F>
A>void check(F T::*)
A>{
A>    F* ptr = &helper; // error C2440: 'initializing' : cannot convert from 'void (__cdecl *)(void)' to 'void (*)(void)'
A>}

A>int main()
A>{
A>    check(&foo::bar);
A>    return 0;
A>}
A>

A>Компайлер рассматривает calling convention как часть сигнатуры, стандартом это не определено, но как быть? В зависимости от установленной по умолчанию calling convention, VC выдает C2440 или ICE.

Тип для 'F' будет выведен как 'void()', соответственно тип 'ptr' будет 'void(*)()', что соответствует типу выражения '&helper'. Т.е. никаких проблем быть не должно. А здесь точно именно этого требуется?
Re[6]: Ограницения template type arguments
От: Юрий Жмеренецкий ICQ 380412032
Дата: 02.02.10 21:19
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ> Но это может привести к сюрпризам, т.к. инстанцирование шаблона функциональным типом и любым другим будет приводить к совершенно разным последствиям.


+ такую функцию невозможно определить.
Re[6]: Ограничения template type arguments
От: Anonim547  
Дата: 02.02.10 23:03
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Имхо, причина там одна — не дать возможность объявления объекта, который имеет 'function type'. В качестве альтернативы можно рассмотреть случай когда такая конструкция приводит к декларации функции, как и в случае c 8.3.5/7. Но это может привести к сюрпризам, т.к. инстанцирование шаблона функциональным типом и любым другим будет приводить к совершенно разным последствиям. Т.е. здесь как мне кажется имеет место "принцип наименьшего удивления": конструкция вида 'T f;' предствляет собой 'object declaration' и только ее, а попытка использования в качестве 'T' функционального типа приводит к ошибке.


Спасибо.

ЮЖ>В случае же с независимыми типами, декларация функции в этом случае — осмысленный шаг со стороны программиста (и результат ни от чего не зависит).


Руководствуясь тем, что IS нацелен больше на разработчиков транслторов, чем на рядовых программистов, префразирую:

Независимый тип известен при определении шаблона и используется в проверке синтаксиса. Зависимый тип станет известен позже при инстанциации.

Что бы исключить какие-то сложности/неоднозначности при определении шаблона, стандарт делает запрет явно. VC не особо проверяет синтаксис внутри шаблона до инстанциации, поэтому успешно транслирует ill-formed example из 14.3.1/3.

ЮЖ>Тип для 'F' будет выведен как 'void()', соответственно тип 'ptr' будет 'void(*)()', что соответствует типу выражения '&helper'. Т.е. никаких проблем быть не должно.


Ситуация не стандартна из-за разных конвенциий вызова.

ЮЖ>А здесь точно именно этого требуется?


К сожалению, автор кода не дал ответа на этот вопрос. Что-то связанное с выводом сигнатуры функций.

Мне кажется, каждый встречающийся в объявлении функции тип выводят по отдедьности, стремясь к:
RT f(A);

что не может попасть под ограничение. Как следствие усомнился, что формулировка стандарта безупречна, как минимум для моего понимания.
Re: Ограницения template type arguments
От: tolgamrab Россия  
Дата: 05.02.10 17:17
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Большинство компайлеров транслируют:

А>
А>template<class T> struct A {
А>static T t; // 1
А>T *pt;      // 2
А>};

А>typedef int function();
А>A<function> a;  // ill-formed: would declare A<function>::t
А>                // as a static member function
А>

А>Comeau ругает строку с // 1
А>

14.3.1/3 If a declaration acquires a function type through a type dependent on a template-parameter and this causes a declaration that does not use the syntactic form of a function declarator to have function type, the program is ill-formed.


А>Проясните ситуацию в случае 2, должен ли компайлер разрешать, или нет? какие причины запрета в 1?


Как раз на днях активно исследовал тему функционального типа, так как еще месяц назад о таком не подозревал.
Дьюхарст пишет по этому поводу, что при помощи typedef'а можно объявлять только нестатические методы класса. Однако в MVS 2008 и в MVS 6.0 прекрасно компилируются и статические методы классов и глобальные функции определенные через typedef.
Описание таких определений приводится в

8.3.5/7 A typedef of function type may be used to declare a function but shall not be used to define a function (dcl.fct.def). [Example:

typedef void F();
F fv; // OK: equivalent to void fv();
F fv { } // ill-formed
void fv() { } // OK: definition of fv


--- end example] A typedef of a function type whose declarator includes a cv-qualifier-seq shall be used only to declare the function type for a nonstatic member function, to declare the function type to which a pointer to member refers, or to declare the top-level function type of another function typedef declaration. [Example:

typedef int FIC(int) const;
FIC f; // ill-formed: does not declare a member function
struct S {
FIC f; // OK
};
FIC S::*pm = &S::f; // OK


--- end example]


Однако 14.3.1/3 похоже запрещает такую же конструкцию для шаблонов. Печально, я только придумал как это можно красиво использовать...
Re: Ограницения template type arguments
От: Roman Odaisky Украина  
Дата: 06.02.10 18:20
Оценка:
Здравствуйте, Аноним, Вы писали:

А>template<class T> struct A {

А>static T t; // 1

А>A<function> a; // ill-formed: would declare A<function>::t


А есть в Boost или еще где-нибудь шаблон, который превращает функции и массивы в указатели, а остальные типы оставляет как есть?
До последнего не верил в пирамиду Лебедева.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.