G ++ 4.7 bug with SFINAE + decltype?

I have built the following MCVE to illustrate the problem I am facing with g ++ 4.7. It uses SFINAE through decltype()

to determine if a functor type with a given argument type can be called (specialized to check if a functor type with no arguments can be called when the type is an argument void

).

#include <iostream>
#include <utility>

template <typename F, typename A>
class can_call_functor_impl
{
private:
    typedef char yes[1];
    typedef char no[2];

    template <typename U>
    static auto test(U *)
        -> decltype(void(std::declval<U const &>()(std::declval<A &>())),
                    std::declval<yes &>());

    template <typename>
    static no & test(...);

public:
    static constexpr bool value = sizeof(test<F>(0)) == sizeof(yes);
};

template <typename F>
class can_call_functor_impl<F, void>
{
private:
    typedef char yes[1];
    typedef char no[2];

    template <typename U>
    static auto test(U *)
        -> decltype(void(std::declval<U const &>()()),
                    std::declval<yes &>());

    template <typename>
    static no & test(...);

public:
    static constexpr bool value = sizeof(test<F>(0)) == sizeof(yes);
};

template <typename F, typename A>
class can_call_functor :
    public std::integral_constant<bool, can_call_functor_impl<F, A>::value> {};

class int_functor
{
public:
    void operator()(int) const;
};

#define PRINT_EXP(e) (std::cout << #e " == " << (e) << std::endl)

int main(void) {
    PRINT_EXP((can_call_functor<int_functor, int>::value));
    PRINT_EXP((can_call_functor<int_functor, short>::value));
    PRINT_EXP((can_call_functor<int_functor, void>::value));
    PRINT_EXP((can_call_functor<int_functor, double>::value));
    PRINT_EXP((can_call_functor<int_functor, int_functor>::value));
}

      

Output in g ++ (Debian 4.7.2-5) 4.7.2:

(can_call_functor<int_functor, int>::value) == 1
(can_call_functor<int_functor, short>::value) == 1
(can_call_functor<int_functor, void>::value) == 1
(can_call_functor<int_functor, double>::value) == 1
(can_call_functor<int_functor, int_functor>::value) == 1

      

This output is troubling, as I expect the third and fifth lines to have a 0 result, and indeed later g ++ and clang will that it should be.

It looks like g ++ 4.7 evaluates to can_call_functor<int_functor, T>::value

be true for anyone T

I can think of.

I strongly suspect that this is a 4.7 specific g ++ bug, but I can't find any evidence of this (issues like these that are especially hard to find on the bug tracker), so I'm looking for the definitive answer

Is this a bug in g ++ 4.7, and if so, is there a workaround? If this is not a bug in g ++, then where is the error in my code?

+3


source to share


1 answer


Is this a g ++ 4.7 bug?

he looks like

in 4.9.1 he produced

(can_call_functor<int_functor, int>::value) == 1
(can_call_functor<int_functor, short>::value) == 1
(can_call_functor<int_functor, void>::value) == 0
(can_call_functor<int_functor, double>::value) == 1
(can_call_functor<int_functor, int_functor>::value) == 0

      

but I can't find any evidence for this (problems like this are especially hard to find on bug trackers)



It could be a mistake https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53788

and if so is there a workaround?

mmmm ....

I can't think of anything good.

move to at least 4.8? You can have multiple gcc installed side by side

+1


source







All Articles