2014-12-05 63 views
3

我已經構建了以下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 ++中的錯誤,那麼代碼中的錯誤在哪裏?

回答

1

這是g ++ 4.7的bug嗎?

這似乎是

在4.9.1它產生

(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 

,但我找不到這個證據(這類問題是特別難以搜索在bug跟蹤器上)

這個可能是bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53788

如果有,是否有解決方法?

嗯....

我想不出什麼好的一個

移動到至少4.8?你可以並排安裝幾個gcc