为什么Clang ++编译器无法编译以下可变参数模板代码?

Nat*_*Nat 8 c++ clang++ c++14

#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() {
}
Run Code Online (Sandbox Code Playgroud)

错误消息是

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.
Run Code Online (Sandbox Code Playgroud)

使用G ++ 4.9.2可以编译相同的代码.我还没找到任何有关Clang的相关错误报告.

Col*_*mbo 10

似乎是一个Clang错误,虽然这些伪析构函数名称的查找可能是缺陷的,并且是开放CWG问题的主题,特别是555和399.

扩展模式的重要部分是

std::get<I>(x).std::tuple_element<I, args_type>::type::~type()
Run Code Online (Sandbox Code Playgroud)

在这里,间位.()是一个伪析构函数名 ; 合格的名称查找然后强制要求

如果伪析构函数名称(5.2.4)包含嵌套名称说明符,则将类型名称 s作为nested-name-specifier指定的作用域中的类型进行查找 .同样,在表单的qualified-id中:

        nested-name-specifier opt   class-name :: ~ class-name

第二个类名在与第一个相同的范围内查找.

type在抬头 std::tuple_element<I, args_type>,在它的发现参考一些类型.请注意,类名是标识符(和语法名称简单模板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)...};
    }
};
Run Code Online (Sandbox Code Playgroud)