gpt4 book ai didi

c++ - Clang 无法在 std::function 实例化中扩展参数包

转载 作者:IT老高 更新时间:2023-10-28 23:21:36 26 4
gpt4 key购买 nike

使用 std=c++17 编译的代码片段作为唯一的编译器标志...

  • ... 使用 GCC 9.1 成功编译。 Godbolt
  • ... 使用 Clang 8.0.0 发出编译器错误(代码段下方的错误)。 Godbolt

问题:这是 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){});

其他研究

正如评论中的其他用户已经指出的那样,制作 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){};
}

最佳答案

TL;DR:这是一个 clang 错误,但标准中也有一个错误。

首先要知道,在 C++ 中,模板分两步处理:

  1. 在定义封闭模板时构建不依赖模板参数的构造。
  2. 在实例化封闭模板时构建依赖的构造。

现在看来,clang 对待 std::function< void(Int<Ts>...) >作为非依赖类型,理由如下:

  1. Int<Ts>是非依赖类型(正确)。
  2. 因此,包含 Int<Ts> 的包扩展(即 Int<Ts>... )也是非依赖的“类型”(?)。
  3. 因为 void(Int<Ts>...) 的所有组件是非依赖的,它是非依赖类型(显然不正确)。
  4. 因为名字std::function是非依赖的,模板参数 void(Int<Ts>...)是非依赖非包扩展类型,std::function< void(Int<Ts>...) >是非依赖类型。

(请注意,“非包扩展”检查使其与 Tuple 的情况不同。)

因此,当 Foo已定义,类型名称Function被视为命名非依赖类型,并立即构建,并且不考虑包扩展(在实例化期间发生)。因此,Function 的所有用途替换为“脱糖”类型std::function< void(int) > .

此外,clang 有 instantiation-dependent 的概念,这意味着构造是不依赖的,但它仍然以某种方式涉及模板参数(例如,构造仅对某些参数有效)。 std::function< void(Int<Ts>...) >被视为依赖于实例化的类型,因此当模板被实例化时,clang 仍然对 using Function = std::function< void(Int<Ts>...) > 执行替换.结果,Function获得正确的类型,但这不会传播到 Function 的使用在 Foo 的定义中.


现在这是标准中的错误。

类型是否依赖在 [temp.dep.type] 中定义:

A type is dependent if it is

  • a template parameter,
  • a member of an unknown specialization,
  • a nested class or enumeration that is a dependent member of the current instantiation,
  • a cv-qualified type where the cv-unqualified type is dependent,
  • a compound type constructed from any dependent type,
  • an array type whose element type is dependent or whose bound (if any) is value-dependent,
  • a function type whose exception specification is value-dependent,
  • denoted by a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent or is a pack expansion [ Note: This includes an injected-class-name of a class template used without a template-argument-list. — end note ] , or
  • denoted by decltype(expression), where expression is type-dependent.

请注意,它并不是说参数列表包含包扩展的函数类型是依赖类型,只是说“由任何依赖类型构造的复合类型”和“异常规范依赖于值的函数类型”是依赖的。在这里都没有帮助。

关于c++ - Clang 无法在 std::function 实例化中扩展参数包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57080425/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com