enable_if + is_same + constexpr函数使MSVC失败(但在Clang,GCC中运行良好)

时间:2019-07-04 11:56:58

标签: c++ visual-c++ language-lawyer

这是一个非常简单的代码:

#include <tuple>
#include <type_traits>
#include <array>

template <class T> struct TypeHolder {};

template<class T, size_t N>
constexpr size_t array_size(TypeHolder<std::array<T,N>>)
{
    return N;
};

using AnyType = int;
template <class V, typename std::enable_if<std::is_same<V,
 std::array<typename V::value_type, array_size(TypeHolder<V>())>>::value, AnyType>::type* = nullptr>
    void test(V & v)
{

}

int main()
{
    std::array<int, 5> x;
    test(x);
}

不要问这段代码是干什么用的。没关系这只是我发现的精简示例。重要的是无论如何它似乎都是有效的C ++ 17代码。

test()仅在V为std::array时才启用(在进一步的SFINAE情况下)。是的,我知道我可以做template<class T, int N> void test(array<T, N>& v),但是这种较脏的模板参数在某些情况下可以帮助我避免int N。 (相信我!)

无论如何,此C ++ 17 代码无法使用C ++ 17安装程序在Visual Studio 2019中编译。 但是它在GCC和Clang中效果很好。

几小时前,我发布了相关问题here。 我唯一能发现的共同点是它们与一些复杂的模板有关,并且它们导致相同的错误代码:

error C2672:  no matching overloaded function found
error C2783:  could not deduce template argument for '__formal'

问题是......

  1. 这是有效的C ++ 17代码吗?
  2. 那为什么MSVC无法编译?
  3. 与我之前的问题有什么关系?
  4. 如果我决定只使用MSVC,应该如何处理?

1 个答案:

答案 0 :(得分:0)

我不知道究竟是什么使MSCV的编译器崩溃,但是用默认类型参数替换默认指针似乎可行:

template <typename V, typename = std::enable_if_t<std::is_same_v<V,
 std::array<typename V::value_type, array_size(TypeHolder<V>())>>, AnyType>>
    void test(V & v)

两者都应为有效的C ++ 17,因为第二个参数可以从V中推导出来。也许constexpr函数还不符合MSCV中的标准。