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?
source to share
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
source to share