c++ - enable_if + 可变参数模板 : is it UB or a MSVC bug?

标签 c++ c++11 visual-c++

GCC 4.9.2、clang 3.5.0 和 MSVC 19 (x86) 按预期编译以下内容:

#include <iostream>
#include <tuple>
#include <type_traits>

using namespace std;

template<size_t I = 0, typename... Tp>
inline typename enable_if<I == sizeof...(Tp), void>::type
    tuple_for_each(tuple<Tp...> &)
{
    cout << sizeof...(Tp) << endl;
}

template<size_t I = 0, typename... Tp>
inline typename enable_if<I < sizeof...(Tp), void>::type
    tuple_for_each(tuple<Tp...> & t)
{
    tuple_for_each<I + 1, Tp...>(t);
}

int main()
{
    auto t = make_tuple(1, 2.3);
    tuple_for_each(t);
}

MSVC 18 (x64) 改为报告以下内容:

Microsoft (R) C/C++ Optimizing Compiler Version 18.00.31101 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(18) : error C2770: invalid explicit template argument(s) for 'enable_if<I<0x01,void>::type tuple_for_each(std::tuple<_Types1...> &)'
        main.cpp(16) : see declaration of 'tuple_for_each'
        main.cpp(24) : see reference to function template instantiation 'void tuple_for_each<0x00,int,double>(std::tuple<int,double> &)' being compiled
main.cpp(18) : error C2893: Failed to specialize function template 'enable_if<I==0x01,void>::type tuple_for_each(std::tuple<_Types1...> &)'
        With the following template arguments:
        'I=0x01'
        'Tp={int, double}'

它是某个地方的 UB 还是只是一个编译器错误? (如果是后者,有什么解决方法吗?)

最佳答案

找到解决方法:

template<size_t I = 0, typename... Tp,
         typename = typename enable_if<I == sizeof...(Tp), void>::type, int = 0>
inline void tuple_for_each(tuple<Tp...> &)
{
    cout << sizeof...(Tp) << endl;
}

template<size_t I = 0, typename... Tp,
         typename = typename enable_if<I != sizeof...(Tp), void>::type>
inline void tuple_for_each(tuple<Tp...> & t)
{
    tuple_for_each<I + 1, Tp...>(t);
}

注意 !=I != sizeof...(Tp) .尝试 < ,你会看到:

Microsoft (R) C/C++ Optimizing Compiler Version 18.00.31101 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
main.cpp(27) : fatal error C1004: unexpected end-of-file found

它本身就很壮观。 (GCC 和 Clang 都适用于 <,但这次不适用于 MSVC19。)


尝试使用

template <bool B, typename T> using enable_alias = typename enable_if<B, T>::type;

初始变体最终会出现在 ICE 中:

Microsoft (R) C/C++ Optimizing Compiler Version 18.00.31101 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

main.cpp
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\xlocnum(1105) : fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'f:\dd\vctools\compiler\cxxfe\sl\p1\c\outdname.c', line 4155)
 To work around this problem, try simplifying or changing the program near the locations listed above.
Please choose the Technical Support command on the Visual C++ Help menu, or open the Technical Support help file for more information

关于c++ - enable_if + 可变参数模板 : is it UB or a MSVC bug?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28796810/

相关文章:

.net - 连接 C/C++ 与 .NET

c++ - 如何确保在不同线程读取变量之前将变量存储到内存中

c++ - QObject内存管理和智能指针

c++ - ODBC 调用 SQLFetch 与 SQLFetchScroll

c++ - 是否可以在其范围之外访问局部变量的内存?

c++ - std::unordered_map::find 使用与 Key 类型不同的类型?

c++ - 模板函数在模板对象上执行成员回调而不提供它的实例

c++ - 为什么 std::is_same 不适用于 bool

C++ Getline 问题(没有重载函数的实例 "getline"

c++ - bool 函数的返回值并将指针作为参数传递