【发布时间】:2019-11-26 13:22:55
【问题描述】:
使用std=c++17作为唯一编译器标志编译的代码的sn-p ...
问题:这是 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 别名为 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){});
其他研究
正如 cmets 中的其他用户已经指出的那样,使 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){};
}
【问题讨论】:
-
对我来说是个 bug。代码似乎没有错误。
-
还有为什么
std::apply不为我工作-.- -
@LightnessRacesinOrbit 是的,我还通过从类外部引用
Foo<…>::Function发现了这一点,然后它表现为一个采用三个整数的函数......甚至Tuple别名也可以正常工作.那么它就是一个错误! -
更新:为此记录了错误:bugs.llvm.org/show_bug.cgi?id=42654(正如 Maarten 亲自问我的那样)
标签: c++ gcc clang c++17 variadic-templates