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

时间:2015-05-12 21:07:03

标签: c++ c++14 clang++

#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编译得很好。我找不到任何关于Clang的相关错误报告。

2 个答案:

答案 0 :(得分:10)

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

扩展模式的重要部分是

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

此处,.()之间的位是伪析构函数名称;合格的名称查找然后强制执行

  

如果伪析构函数名称(5.2.4)包含嵌套名称说明符,    type-name 被查找为由指定范围内的类型   嵌套名说明符。同样,在以下形式的 qualified-id 中:

     

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

     

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

即。在type中查找std::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)...};
    }
};

答案 1 :(得分:0)

有趣的是,来自IBM mentionedcouple workarounds的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)...};