我已經構建了以下MCVE來說明我使用g ++ 4.7時遇到的問題。它通過decltype()
使用SFINAE來確定是否可以使用給定的參數類型調用仿函數類型(專門用於測試當參數類型爲void
時是否可以使用無參數調用仿函數類型)。g ++ 4.7 SFINAE + decltype的bug?
#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));
}
輸出對於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
該輸出是令人不安的,因爲我希望第三和第五行到具有0的結果,並且確實later g++ and clang一致認爲這應該是這種情況。
看來,g ++ 4.7評估can_call_functor<int_functor, T>::value
爲真正的任何T
我可以想出。
我強烈懷疑這是一個特定於4.7的g ++ bug,但我找不到任何證據(這些類型的問題在bug追蹤器上搜索起來特別困難),所以我正在尋找一個定義回答:
這是一個g ++ 4.7錯誤,如果有的話是否有解決方法?如果它不是g ++中的錯誤,那麼代碼中的錯誤在哪裏?