包扩展失败与g++4.9.0,但工作与clang++3.4
Pack expansion failure with g++ 4.9.0, but works with clang++ 3.4
对于以下代码:
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对修复的评论是:
通过实现当前提出的核心方向来修复断言1430期。不允许将包扩展用作别名的参数模板,除非相应的参数是参数包。
例如,参考的核心缺陷包括与您的代码基本相同的代码:
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>({});
}
缺陷注释:
在处理此示例时存在实现差异。
缺陷给出的早期示例是一个更困难的情况,它似乎要求模板别名不能充当模板的透明别名。由于这个实现问题,委员会显然倾向于禁止以某些方式使用模板别名,编译器实现者似乎也在采用这种解决方案。
因此,我的理解是,根据当前编写的规范,此代码是有效的,但存在实现问题,委员会最终可能会禁止它。
模板别名的使用应该是这样的,即别名可以在使用的地方扩展。
在您定义之后
template <typename T, typename... Ts>
using Tail = Set<Ts...>;
你使用
Tail<Ts...>
但是这不能被涉及CCD_ 1的任何东西所取代。
(我必须承认,我很难找到支持这种解释的引用,所以我不确定这是标准规定的,还是编译器实现的。(
相关文章:
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 检查工作正常的 CXX 编译器:/cygdrive/c/cygwin64/bin/clang++ -- 已损坏
- C++指向成员的指针的类内初始化会使 MSVC 失败(但 GCC/Clang 工作)
- 在 GCC 中工作的外行构造函数模板在 Clang 中失败
- GCC 和 clang 抛出"no matching function call"但 msvc (cl) 按预期编译和工作
- 在 gcc 上自己的元组实现段错误,同时在 clang 中工作
- dynamic_cast 在 clang 上无法跨模块边界工作
- 继承默认构造函数在 gcc 中失败并在 clang 中工作,哪个有错误?
- 构造函数上的SFINAE在VC2017中工作,但在clang / gcc中不起作用
- 无限递归模板实例化使用clang时GCC工作正常
- "Typedef redefinition with different types" Clang中关于工作MSVC代码的错误
- 变量args SFINAE默认构造函数在clang中工作,但在Visual Studio 2015中失败
- Clang+VS2013:包含c++标头时出错(vs2012:正在工作)
- SFINAE 不在 llvm/clang 上工作
- cpp 模板<>使用 clang 格式 3.6 的间距无法按预期工作
- 对于Clang和Codegen的MSVC 2015,我如何让ast dump工作
- Clang 无法在 std::experimental::optional(可选)中正常工作
- 派生类的特化std::hash可以在gcc中工作,而不是在clang中
- 带有inttype的枚举类的Printf不能在clang中工作
- 如何让c++ 0x / c++ 11风格的基于范围的for循环与clang一起工作