Вывод сигнатуры функции

Тема в разделе "LANGS.C", создана пользователем _DEN_, 26 янв 2010.

  1. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    J0E
    То, что VC++ компилит ill-formed код - IMHO, это скорее фича в данном случае. Расширение компилятора. Это характерно для каждого неакадемического компилятора, GCC в этом плане ничем не лучше.
    Хотя да, могут быть проблемы с кодом, который полагается на это ограничение Стандарта (например, для SFINAE).
    А в чём состоит баг Comeau? Правильно делает, что не компилит. :derisive:

    Разрешено. Точнее явно не запрещено, AFAIK.
    Такой код
    Код (Text):
    1. struct S
    2. {
    3. function t;
    4. };
    Comeau компилит.
     
  2. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    J0E

    Не понял, где там баг? Можно конкретный пример кода?
     
  3. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    "If a declaration ... to have function type..."

    В первом посте происходит определение (и объявление) указателя, и его типом является никак не "function type".
     
  4. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    Явно разрешено (8.3.5/7):

    Код (Text):
    1. typedef void F();
    2.  
    3. struct A
    4. {
    5.   F foo;
    6. };
    7.  
    8. void A::foo() {}
    9.  
    10. //...
    11.  
    12. template<class>
    13. struct B
    14. {
    15.   F bar;
    16. };
    17.  
    18. template<class T>
    19. void B<T>::bar() {}
     
  5. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    В не шаблонных выражениях зависимый от аргумента шаблонна тип не может быть ни разрешен, ни запрещен, его там и быть не может )
    8.3.5/7 говорит о "A typedef of function type".

    Твои же слова: " 'F' имеет тип 'void(void)' или просто 'void()' - это так называемый 'function type'". Указателя, не указателя, какая разница, или мы по разному понимаем "a declaration acquires a function type"?

    Почему же ты считаешь, что тебе обязаны отвечать на вопросы, когда ты сам игнорируешь других?
    Конкретный пример был показан в #34, Комо ловит ошибку только в одном из определений.
     
  6. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    только в одном из объявлений*
     
  7. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Вольный перевод стандарта:

    14.3.1 Аргументы шаблона - типы

    3 Если в объявление вовлечен функциональный тип, _зависимый_ от параметра шаблона, и это проводит к объявлению (имеющему функциональный тип), которое не использует синтаксис объявления функции, программа не корректна.

    Декларация функция описана в 8.3.5 и включает в себя указатели на функции, в том числе и члены.
     
  8. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    Не теряй контекст. Чем здесь является 'function':

    Код (Text):
    1. struct S
    2. {
    3. function t;
    4. };
    ?

    Как это какая разница? есть 'function type', есть 'pointer type', декларации соответственно будут называться 'function declaration' и 'object declaration'. (в примере выше - S::t - не объект). 14.3.1/3 к исходному примеру не имеет отношения, 'F' принимает участие в объявлении (и определении) указателя.
     
  9. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    nop_ - сам не теряй контекст. function в твоем куске кода ничем не является.
     
  10. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    Так же как в коде, который привел green (я ему отвечал). А вот в контексте обсуждения несколько раз была упомянута конструкция 'typedef int function();'. Кроме того у меня в ответе в качестве примера явно используется 'typedef void F();'.
     
  11. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Указателя на что? На функциональный тип. Тебя не удивляет что они описаны в стандарте не в 8.3.1 Pointers, а в 8.3.5/9

    In the declarator (*pif)(const char*, const char*), the extra parentheses are necessary to indicate that indirection through a pointer to a function yields a function, which is then called.

    Имеем объявление, в которое вовлечен функциональный тип, но это не выглядит как объявление с вовлечением функционального типа.

    ЗЫ указатель не определяется, а объявляется с инициализацией.
     
  12. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Я ее и привел, как пример ill-formed
    Код (Text):
    1. template<class T> struct S {
    2.   T t;
    3. };
    4.  
    5. template<class T> void f(){
    6.   T t;
    7. }
    8.  
    9. typedef int function();
    10.  
    11. S<function> a;
    12.  
    13. int main()
    14. {
    15.   f<function>();
    16. }
     
  13. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    В контексте последнего

    struct S
    {
    function t;
    };

    не в тему. В последнем случае function не зависит от параметра шаблона, не надо уходить в с торону.
     
  14. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    Во первых: 8.3.5/9 не является нормативным, т.к. содержит только примеры (помеченные как [Example:...]). Во вторых: обявления указателей описаны именно в 8.3.1, обявления указателей на члены - в 8.3.3.

    Берем тот самый злополучный пример:

    Код (Text):
    1. template <class T, class F>
    2. void check(F T::*)
    3. {
    4.     F* ptr = &helper;
    5. }
    8.3.1/1
    'F* ptr' ==> T = 'F', D = '* ptr'

    Тип идентификатора 'ptr' представляет собой указатель на 'F'. Это object declaration, посмотри в 7/5 - там проводится четкое разграничение между 'function declaration' и 'object declaration'.

    Только вот тип 'ptr' относится к 'object type', а не 'function type', о котором идет речь в 14.3.1/3.

    В этом примере инициализация не влияет на объявление/определение. Здесь объявление совмещено с определением.
     
  15. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    Вот он, контекст:

    Про независимость от параметров шаблона первый сказал как раз ты ;) Я только привел ссылку на стандарт, в которой проясняется этот момент.
     
  16. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Нешаблоны - не интересны, это не по теме. pointer to T тоже не по теме, не подменяй понятия.

    Тема о фукциональных типах, которые зависят от аргумента шаблона, и используются в объявлениях содержащих функциональный тип. Пусть там будет хоть 20 поитеров, это не меняет картины.

    Применяя 7/5 ты хочешь показать, что объявив функциональный тип через typedef, а потом используя typedef для объявления объекта-поинтера (что семантически то же самое) можно легально обойти запрет стандарта? :)

    Можно привести альтернативное толкование 4.3.1/3, а не искать опровержения в других?
     
  17. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    реакция напоминает некоторых из http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29927
     
  18. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    А это что - 'F* ptr' ?

    Кардинально меняет.

    Ну нет в исходном примере выделенного. Есть объявление(определение) которое имеет 'object type'.

    Ты еще скажи что так нельзя:

    Код (Text):
    1. template<class> struct A{};
    2.  
    3. template<class T>
    4. void f()
    5. {
    6.   A<void(T)> x;
    7. }
    8.  
    9. int main()
    10. {
    11.   f<int>();
    12. }
    Применяя 7/5 я показал ровно то, что стандарт четко различает 'object declaration' и 'function declaration', не больше, не меньше.

    Твое подходит. Просто ты не видишь разницу между "имеющему функциональный тип" и имеющему 'object type'. Указатель в принципе не может иметь функциональный тип.

    По ссылке http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29927 обсуждают другой пример. Там действительно пытаются объявить функцию (а не указатель).
     
  19. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    J0E
    Сорри, я невнимательно смотрел код суслика. :derisive:
    Теперь вижу, что ты подразумевал под багом в Comeau - то что он компилит код
    Код (Text):
    1. template<class T> void f(){
    2.   T t;
    3. }
    4.  
    5. typedef int function();
    6.  
    7. int main()
    8. {
    9.   f<function>();
    10. }
    который ill-formed согласно
    Действительно, похоже баг...
    Хотя в данном случае логичнее было бы поправить Стандарт, а не Comeau. :derisive:
    Если в случае классового шаблона это ограничение ещё можно понять, то для шаблона ф-ции оно, IMHO, совершено лишнее - декларации внутри тела ф-ции никак не отражаются на внешних свойствах ф-ции.
     
  20. J0E

    J0E New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2008
    Сообщения:
    621
    Адрес:
    Panama
    Это подмена понятий.

    F f, * ptr; // got it?

    Код (Text):
    1. template <class T, class F>
    2. void check(F T::*)
    3. {
    4.   typedef F F_t; // ill-formed
    5.   F_t * ptr = &helper;
    6. }
    this causes a declaration to have both object and function types.

    > Указатель в принципе не может иметь функциональный тип.

    ты путаешь значения is & has, "иметь" в твоем предложении было бы is в оригинале.

    3.9.2 Compound types
    1
    — pointers to void or objects or functions (including static members of classes) of a given type, 8.3.1;
    2 These methods of constructing types can be applied recursively; restrictions are mentioned in 8.3.1, 8.3.4,
    8.3.5, and 8.3.2.