g ++ 4.7 SFINAE + decltype错误?

时间:2014-12-05 20:32:58

标签: c++ c++11 g++ sfinae

我构建了以下MCVE来说明我使用g ++ 4.7时遇到的问题。它通过decltype()使用SFINAE来确定是否可以使用给定的参数类型调用仿函数类型(专门用于测试在参数类型为void时是否可以在没有参数的情况下调用仿函数类型)。 / p>

#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一致认为应该是这种情况。

对于我能提出的任何can_call_functor<int_functor, T>::value,g ++ 4.7似乎评估T为真。

我强烈怀疑这是一个特定于4.7的g ++错误,但我找不到任何证据(这些问题特别难以在bug跟踪器上搜索),所以我正在寻找明确的答案:

这是一个g ++ 4.7错误,如果有的话有解决方法吗?如果它不是g ++中的错误那么我的代码中的错误在哪里?

1 个答案:

答案 0 :(得分:1)

  

这是一个g ++ 4.7错误吗?

似乎是

on 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追踪器上搜索)

这个可能是错误https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53788

  

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

...嗯

我想不出任何好的

移至至少4.8?你可以并排安装几个gcc