编译的代码片段std=c++17
作为唯一的编译器标志...
- ...使用 GCC 9.1 成功编译。Godbolt https://godbolt.org/z/QKJomx
- ...使用 Clang 8.0.0 发出编译器错误(代码片段下方的错误)。Godbolt https://godbolt.org/z/S7tB5K
问题:这是 Clang 编译器中的错误,还是 GCC 接受此代码的错误,还是有其他原因?
#include <functional>
#include <tuple>
template <typename... Ts>
struct Foo
{
template <typename T>
using Int = int;
// Function that accepts as many 'int' as there are template parameters
using Function = std::function< void(Int<Ts>...) >;
// Tuple of as many 'int' as there are template parameters
using Tuple = std::tuple< Int<Ts>... >;
auto bar(Function f)
{
std::apply(f, Tuple{}); // Error with Clang 8.0.0
}
};
int main()
{
auto foo = Foo<char, bool, double>{};
foo.bar([](int, int, int){});
}
令我感到奇怪的是,Clang 的错误表明它已成功别名Tuple
as std::tuple<int, int, int>
但它错误地别名Function
就这样std::function<void(int)>
,只有一个而不是三个参数。
In file included from <source>:2:
In file included from /opt/compiler-explorer/gcc-8.3.0/lib/gcc/x86_64-linux-gnu/8.3.0/../../../../include/c++/8.3.0/functional:54:
/opt/compiler-explorer/gcc-8.3.0/lib/gcc/x86_64-linux-gnu/8.3.0/../../../../include/c++/8.3.0/tuple:1678:14: error: no matching function for call to '__invoke'
return std::__invoke(std::forward<_Fn>(__f),
^~~~~~~~~~~~~
/opt/compiler-explorer/gcc-8.3.0/lib/gcc/x86_64-linux-gnu/8.3.0/../../../../include/c++/8.3.0/tuple:1687:19: note: in instantiation of function template specialization 'std::__apply_impl<std::function<void (int)> &, std::tuple<int, int, int>, 0, 1, 2>' requested here
return std::__apply_impl(std::forward<_Fn>(__f),
^
<source>:19:14: note: in instantiation of function template specialization 'std::apply<std::function<void (int)> &, std::tuple<int, int, int> >' requested here
std::apply(f, Tuple{}); // Error
^
<source>:26:9: note: in instantiation of member function 'Foo<char, bool, double>::bar' requested here
foo.bar([](int, int, int){});
额外的研究
正如评论中的其他用户已经指出的那样,Int
模板别名取决于类型T
修复问题:
template <typename T>
using Int = std::conditional_t<true, int, T>;
我还发现了其他一些事情,只是参考Function
从外部输入也可以使其按预期/期望工作:
int main()
{
auto f = Foo<char, bool, double>::Function{};
f = [](int, int, int){};
}