以下文件确实可以在 Visual Studio 编译器和 Clang for Microsoft Codegen 上编译,但结果却大不相同。
在 Visual Studio 中,它计算参数列表中动态矩阵的数量(这是我的预期行为)。相反,在 clang 中,它会计算动态矩阵的数量,直到遇到第一个静态矩阵。 (输出在main.cpp文件中,格式为(VS, Clang))
我还能够在 gcc 7.1 和 icc 17 上进行复制,它们都遵循 clang 的相同行为
删除 meta
命名空间以及添加 using
声明可以解决问题,但我不明白为什么
Working example (cl 2017 RTW vs gcc 7.1)
#include <tuple>
template <size_t x = 0>
class M{};
template <>
class M<0>{};
// Note, if this is removed the problem disappears
namespace meta
{
inline auto f()
{
return std::make_tuple();
}
template <std::size_t x, typename ... Args>
auto f(const M<x>& , Args && ... args)
{
return f(args...);
}
template <typename ... Args>
auto f(const M<>& first, Args && ... args)
{
return std::tuple_cat(std::make_tuple(first), f(args...));
}
}
#include <iostream>
int main(int, char* [])
{
M<1> a;
M<> b;
std::cout << std::tuple_size<decltype(meta::f(a, a, a))>::value << "\n"; // (0, 0)
std::cout << std::tuple_size<decltype(meta::f(a, a, b))>::value << "\n"; // (1, 0)
std::cout << std::tuple_size<decltype(meta::f(a, b, a))>::value << "\n"; // (1, 0)
std::cout << std::tuple_size<decltype(meta::f(a, b, b))>::value << "\n"; // (2, 0)
std::cout << std::tuple_size<decltype(meta::f(b, a, a))>::value << "\n"; // (1, 1)
std::cout << std::tuple_size<decltype(meta::f(b, a, b))>::value << "\n"; // (2, 1)
std::cout << std::tuple_size<decltype(meta::f(b, b, b))>::value << "\n"; // (3, 3)
}
输出 Visual Studio
0
1
1
2
1
2
3
输出clang/gcc/icc
0
0
0
0
1
1
3
最佳答案
我打开了一个 bug report在 clang 上,很快就发现这确实是一个错误,只是不是在 clang 中,而是在 MSVC 中。我要在这里无耻地窃取 Richard Smith 的答案:
This is an MSVC bug, due to their missing / incorrect implementation of two-phase name lookup.
Within the second definition of f:
template <std::size_t x, typename ... Args> auto f(const M<x>& , Args && ... args) { return f(args...); }
... the third 'f' has not yet been declared and thus is not found by unqualified name lookup. So once the recursion reaches this overload, it can never "go back" to the third overload.
If the namespace is removed, the third overload can be found by argument-dependent name lookup.
关于c++ - Visual Studio 和 Clang 不同的行为模板元编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44717602/