[GCC/C++11] Bug?
От: zaufi Земля  
Дата: 02.03.13 13:32
Оценка: 14 (1)
hi all

потребовался мне тут чекер компаил-таймный чтобы проверять можно ли некий callable-type вызвать с заданными параметрами.
собственно сам чекер, дело не хитрое, но пепец подкрался откуда не ждал: в тесте он попросту не работал ;( я некоторое (заметное) время я еще пробовал его реанимировать и так и эдак печатая разнообразный debug spam про типы тут участвующие -- все казалось бы хорошо, но финальный чекер не работает хоть тресни ;(

затрахавшись с ним в конец (и уже собираясь сдаваться) я попробовал собрать тестик clang'ом 3.2 -- и он зараза работает как и ожидалось!
я уже было сильно расстроился и собрался писать багу в GCCшную багзилу, сделал минимальный пример (см ниже), но все таки решил слегка его изменить (см вариант #1 и #2 в примере) -- оказалось что мой изначальный вариант (без add_pointer) ни в какую не хочет работать (что очевидно бага), но второй работает замечательно (что меня все таки радует)...

// kate: hl C++11;
#include <iostream>
#include <type_traits>
#include <utility>

struct is_callable_with_checker
{
    typedef char yes_type;
    typedef char (&no_type)[2];

    template <typename...>
    static no_type test(...);

#if 1
    // case #1 (original): simple add '*' to a deduced type to form a pointer type parameter
    template <typename Callable, typename... Args>
    static yes_type test(
        /*const*/ decltype(
            std::declval<Callable>()(std::forward<Args>(std::declval<Args>())...)
          , void()
          )* /*const*/
      );
#else
    // case #2: form a pointer type via metafunction
    template <typename Callable, typename... Args>
    static yes_type test(
        typename std::add_pointer<
            decltype(
                std::declval<Callable>()(std::forward<Args>(std::declval<Args>())...)
              , void()
              )
          >::type
      );
#endif
};

template <typename Callable, typename... Args>
struct is_callable_with
  : std::is_same<
        decltype(is_callable_with_checker::template test<Callable, Args...>(nullptr))
      , is_callable_with_checker::yes_type
      >
{};

// Some functor w/ overloaded operator(...)
struct test
{
    int operator()(int) const
    {
        return 123;
    }
    double operator()(int, double) const
    {
        return 123.123;
    }
};

int main()
{
    // expect 1
    std::cout << is_callable_with<test, int>::type::value << std::endl;
    // expect 1
    std::cout << is_callable_with<test, int, double>::type::value << std::endl;
    // expect 0
    std::cout << is_callable_with<test, int, std::ostream&>::type::value << std::endl;

    return 0;
}


собственно вопросы к просвещенной общественности:
0) кто видит разницу в получаемом типе параметра функции `yes_type test(...)`?
1) если ее нету, очевидно это бага -- может кто знает с чем (с какой другой багой) она связана? может уже зарепортили что-то похожее?

PS: кастую Masterkent'а
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.