Clang 编译器为什么无法编译以下variadic模板代码

Why does Clang++ compiler fail to compile the following variadic template code?

本文关键字:variadic 代码 编译 编译器 为什么 Clang      更新时间:2023-10-16
#include <string>
#include <iostream>
#include <tuple>
#include <utility>

template<typename... T> struct test {
    using args_type = std::tuple<T...>;
    args_type x;
    template<std::size_t... I>
    void callme(std::index_sequence<I...>) {
        int _[] = {(std::get<I>(x).std::tuple_element<I, args_type>::type::~type(), true)...};
    }
};
int main() {
}

错误消息是

clang-3.7  -std=gnu++1y  -Wc++14-extensions test.cpp
test.cpp:15:56: error: expected ')'
        int _[] = {(std::get<I>(x).std::tuple_element<I, args_type>::type::~type(), true)...};
                                                       ^
test.cpp:15:20: note: to match this '('
        int _[] = {(std::get<I>(x).std::tuple_element<I, args_type>::type::~type(), true)...};
                   ^
1 error generated.

与G 4.9.2相同的代码似乎可以弥补。我还找不到任何相关的错误报告。

似乎是一个叮当虫,尽管这种伪毁灭者名称的查找可能是违反的,并且对开放CWG问题的主题,特别是555和399。

膨胀模式的重要位是

std::get<I>(x).std::tuple_element<I, args_type>::type::~type()

在这里, .()之间的位是 pseudo-destructor-name ;然后,合格的名称查找要求

如果A pseudo-Destructor-name (5.2.4)包含a nested-name-specifier type-name s被查找为类型 Nested-Name-Pesifier 。同样,在表格的A 合格-ID中:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp;class-name :: ~ class-name

第二个 class-name 在与第一个的范围相同的范围中查找。

即。typestd::tuple_element<I, args_type>中查找,发现它指某种类型。请注意, class-name 是标识符(和 simple-template-id s)的语法名称,无需参考实际类。std::get<I>(x).std::tuple_element<I, args_type>::type::~type然后是指type的破坏者。

具有辅助功能的解决方法:

template <typename T>
void destroy(T& p) {p.~T();}
template<typename... T> struct test {
    using args_type = std::tuple<T...>;
    args_type x;
    template<std::size_t... I>
    void callme(std::index_sequence<I...>) {
        int _[] = {(destroy(std::get<I>(x)), 0)...};
    }
};

有趣的是,来自IBM的HSTONG提到了一些可以更好地工作的解决方法。

int _[] = {(std::get<I>(x).::std::tuple_element<I, args_type>::type::~type(), true)...};

int _[] = {(std::get<I>(x).std::template tuple_element<I, args_type>::type::~type(), true)...};