c++ - 使用 g++ 4.9.0 打包扩展失败,但适用于 clang++ 3.4

标签 c++ templates c++11 variadic-templates

对于下面的代码:

template <typename... Ts>
struct Set {};

template <typename T, typename... Ts>
using Tail = Set<Ts...>;

template <typename T, typename TS>
struct MemberOf;

template <typename T, typename... Ts>
struct MemberOf<T, Set<T, Ts...>> {
    static constexpr bool value = true;
};

template <typename T>
struct MemberOf<T, Set<>> {
    static constexpr bool value = false;
};

template <typename T, typename... Ts>
struct MemberOf<T, Set<Ts...>> {
    static constexpr bool value = false || MemberOf<T, Tail<Ts...>>::value;
};

g++ 4.9.0 给出:

ts.cpp:27:63: error: pack expansion argument for non-pack parameter 'T' of alias template 'template<class T, class ... Ts> using Tail = Set<Ts ...>'
     static constexpr bool value = false || MemberOf<T, Tail<Ts...>>::value;
                                                               ^
ts.cpp:4:11: note: declared here
 template <typename T, typename... Ts>
           ^
ts.cpp:27:66: error: template argument 2 is invalid
     static constexpr bool value = false || MemberOf<T, Tail<Ts...>>::value;
                                                                  ^

clang++ 3.4 在没有任何诊断的情况下编译它。对我来说它看起来像是一个 g++ 错误,但只是想确认一下。

附录:因此,根据下面的出色答案,问题似乎是 pack 参数必须与别名模板中的 pack 参数完全对应。换句话说:

template <typename T, typename... Ts>
using Tail = Set<Ts...>;

template <typename... Ts>
using Alias1 = Tail<Ts...>; // ERROR, Ts doesn't correspond directly to the pack in Tail.

template <typename... Ts>
using Alias2 = Tail<int, Ts...>; // Okay, now it does.

最佳答案

由于修复了以下错误,较新版本的 clang 现在也拒绝您的代码:

http://llvm.org/bugs/show_bug.cgi?id=18401

Richard Smith 对修复的评论是:

Fix assert by implementing the current proposed direction of core issue 1430. Don't allow a pack expansion to be used as an argument to an alias template unless the corresponding parameter is a parameter pack.

引用 core defect例如,包括与您的代码基本相同的代码:

template<class... x> class list{};
template<class a, class... b> using tail=list<b...>;
template <class...T> void f(tail<T...>);

int main() {
  f<int,int>({});
}

以及缺陷说明:

There is implementation variance in the handling of this example.

缺陷给出的早期示例是一个更困难的情况,它似乎要求模板别名不能作为模板的透明别名。由于这个实现问题,委员会显然倾向于禁止以某些方式使用模板别名,而编译器实现者似乎正在采用该解决方案。

所以我的理解是,这段代码在当前编写的规范下是有效的,但存在实现问题,委员会最终可能会禁止它。

关于c++ - 使用 g++ 4.9.0 打包扩展失败,但适用于 clang++ 3.4,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23416127/

相关文章:

c++ - std::is_sorted 和 strictly less 比较?

c++ - 在 Visual Studio 中模拟一个简单的内存泄漏,结果有点困惑

c++ - 传递给着色器的颜色不起作用

templates - 获取 Sitecore 模板 A 或模板 B 下的所有子项目

python - 在 Python 中使用可变数量的 .format() 参数进行格式化

c++ - 查找函数链以获得所需的输出

c++ - 我可以在 C++ 中移动临时对象的属性吗?

c++ - 用于显示字符串 | 的每个字符的 for 循环C++

c++ - 使用不相关的指针移动 shared_ptr

c++ - 在构造函数初始化器中使用 map 的初始化器列表