compile time class member detection

Тема в разделе "LANGS.C", создана пользователем scf37, 29 мар 2007.

  1. _DEN_

    _DEN_ DEN

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

    Мощно :)
     
  2. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    _DEN_

    оно вообще компилится? ;)
     
  3. _DEN_

    _DEN_ DEN

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

    Да, все работает. Там есть ссылка на статью. Прочитал - понравилось :) Очень тонкий и изящный способ :)
     
  4. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    _DEN_
    странно. Comeau, Intel:
    more than one instance of overloaded function "omni::test_for_swap

    а вот если вместо
    template <class T>
    double test_for_swap(const T&, ...);

    объявить
    double test_for_swap(...);
    все пучком
     
  5. _DEN_

    _DEN_ DEN

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

    В таком случае не работает на 8.0 :)

    Че-то камю кстати гонит - там вроде все по стандарту получаицо. Действительно странно.
     
  6. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    _DEN_
    Код (Text):
    1. template <class T>
    2. char test_for_swap(const T&, member_wrapper<void (T::*)(T&), &T::swap>* p = 0);
    3.  
    4. template <class T>
    5. double test_for_swap(const T&, ...);
    6. ...
    7. test_for_swap(t)
    не уверен.

    дефолтный аргумент участвует в определении жизнеспособности функции, а при определении наилучшей - нет.
    по первому аргументу (const T&) получается неопределенность

    P.S. поправьте, если не так
     
  7. _DEN_

    _DEN_ DEN

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

    А как же SFINAE? Да и ... имеет самый низкий приоритет при матчинге. У шаблона приоритет выше - судя по статье, на которую ссылка с RSDN тут как раз все по понятиям.
     
  8. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    _DEN_
    при чем тут SFINAE?

    RedLord
    а это, кстати, откуда?
     
  9. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    _DEN_
    SFINAE позволяет компилятору безболезненно удалить из набора первую функцию, если неудался вывод для member_wrapper (другими словами у T нет мембера swap или swap не есть void (T::*)(T&) ).
    в противном случае в наборе остается две функции и между ними нужно выполнить разрешение перегрузки
    Nouzui
    13.3.3 Best Viable Function (ISO/IEC 14882:2003)
     
  10. _DEN_

    _DEN_ DEN

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

    Ну так шаблон имеет более высокий приоритет. Тоесть например:

    Код (Text):
    1. template <class T>
    2. void foo(int i, T* t = 0);
    3.  
    4. void foo(int i, ...);
    5.  
    6. int a = 10;
    7. foo(a); // Будет вызвана первая функция.
    Разве не так?
     
  11. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    _DEN_
    1. там оба темплейта
    2. приоритет темплейта наоборот ниже:
    RedLord
    что-то я в 13.3.3 не нашел..
    в 13.3.2 есть:
    впрочем, к теме это мало относится, поскольку второй аргумент в данном случае задан явно, а вот то, что приоритет ... ниже аргумента с определенным типом, верно:
     
  12. _DEN_

    _DEN_ DEN

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

    Ага, значит меня просто MSVC 8.0 обманывает. Вот такой код.

    Код (Text):
    1. template <class T>
    2. void foo(T t, T* p = 0)
    3. {
    4. }
    5.  
    6. template <class T>
    7. void foo(T t, ...)
    8. {
    9. }
    10.  
    11. int main()
    12. {
    13.     int x = 0;
    14.     foo(x);
    15.     return 0;
    16. }
    Поганый МСВЦ вызывает 1-ю, а камю говорит вот что:

    "ComeauTest.c", line 14: error: more than one instance of overloaded function "foo"
    matches the argument list, the choices that match are:
    function template "void foo(T, T *)"
    function template "void foo(T, ...)"
    The argument types that you used are: (int)
    foo(x);
    ^
     
  13. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    вызывается вторая..

    а про второй случай мы сейчас и спорим. я пока не понял, что стандарт говорит по этому поводу..
     
  14. _DEN_

    _DEN_ DEN

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

    Компиллер? :)
     
  15. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    Nouzui

    пункт 13.3.3 Best Viable Function
    пункт 14.5.5.2
     
  16. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    Nouzui
    Код (Text):
    1. template <class T>
    2. void foo(T t, T* p = 0)
    3. {
    4. }
    5.  
    6. template <class T>
    7. void foo(T t, ...)
    8. {
    9. }
    10.  
    11. int main()
    12. {
    13.     int x = 0;
    14.     foo(x);
    15.     return 0;
    16. }
    насколько я понял, при foo(x) дефолтные аргументы и ... отбрасываются и разрешение перегрузки проходит только по первому параметру - а он у обоих функций с одним рангом.
     
  17. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    RedLord
    да я уже и сам понял, что стормозил по поводу "второй аргумент в данном случае задан явно"
    выходит, MS не зря добавила свою __if_exists?
     
  18. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    ps:
    соррь, не сказал сразу: вся линейка MS: 6.0, 7.1 и 8.0
    на других сейчас проверить не могу..
     
  19. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Nouzui
    __if_exists плох тем, что не различает перегруженных функций.
     
  20. Nouzui

    Nouzui New Member

    Публикаций:
    0
    Регистрация:
    17 ноя 2006
    Сообщения:
    856
    ну ладно, раз вопрос стоит только в разрешении темплейтов, можно так:
    Код (Text):
    1. template <class T, T val>
    2. struct member_wrapper{};
    3.  
    4. template <class T>
    5. char test_for_swap(const T&, const T&, member_wrapper<void (T::*)(T&), &T::swap>* p = 0);
    6.  
    7. template <class T>
    8. double test_for_swap(const T&, ...);
    9.  
    10. template <class T>
    11. struct has_member_swap
    12. {
    13.     static T t;
    14.     static const bool value = (1 == sizeof(test_for_swap(t, t)));
    15. };
    на MS 8.0 прокатывает за исключением случаев, когда проверяемый мембер инкапсулирован (private или protected)
    с последним случаем, похоже, вообще задница.. кстати, похоже и мелкомягкие расширения тут тоже не помогут