MSVC无法评估enable_if内部的constexpr函数

时间:2018-07-07 19:41:54

标签: c++ visual-c++ c++14

考虑一个简单的实用函数来计算合取,并使用该实用程序来确保std::tuple中的类型都相等。

#include <type_traits>
#include <tuple>

constexpr auto all() noexcept -> bool { return true; }

template <class... Bools>
constexpr auto all(bool const x, Bools... xs) noexcept -> bool
{
    return x && all(xs...);
}

template <class T, class = void>
struct foo;

template <class T, class... Ts>
struct foo< std::tuple<T, Ts...>
          , std::enable_if_t<all(std::is_same<T, Ts>::value...)>
          > {
};

int main()
{
    foo<std::tuple<int, int>> x;
}

此代码适合使用GCC和Clang,但不适用于MSVC。 Here's一个godbolt链接。所以我想知道,这是MSVC错误还是仅仅是我遗漏了一些东西?

1 个答案:

答案 0 :(得分:4)

我想这是MSVC错误。如果支持C ++ 17,我建议改用std::conjunction。在C ++ 14下,作为一种解决方法,可以从前一个链接复制“可能的实现”:

#include <type_traits>
#include <tuple>

template<class...> struct conjunction : std::true_type { };
template<class B1> struct conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct conjunction<B1, Bn...> 
    : std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
template<class... B>
constexpr bool conjunction_v = conjunction<B...>::value;

template <class T, class = void>
struct foo;

template <class T, class... Ts>
struct foo< typename std::tuple<T, Ts...>
        , std::enable_if_t<conjunction_v<std::is_same<T, Ts>...>>
        > {
};

int main()
{
    foo<std::tuple<int, int>> x;
}