SFINAE是否会干扰模板偏序?PETE库ForEach偏特化歧义问题咨询
问题原因
你遇到的偏特化歧义是g++ 9.x版本处理带默认值的模板参数偏序时的典型问题:原生PETE的ForEach偏特化没有显式声明第四个Enable参数的匹配值,仅隐式使用主模板的默认void值,编译器做偏序比较时不会将未显式出现在特化参数列表中的参数纳入特化程度判断,导致无法识别你新增的带enable_if的特化优先级更高。
解决方案
只需给原生PETE的ForEach偏特化(你标注的编号1)显式补充第四个参数为void即可,不需要修改原有实现逻辑:
// 修改后的编号1 原生PETE实现 template<class Op, class A, class B, class FTag, class CTag> // 显式指定第四个参数为void,让编译器参与偏序比较 struct ForEach<BinaryNode<Op, A, B>, FTag, CTag, void > { typedef typename ForEach<A, FTag, CTag>::Type_t TypeA_t; typedef typename ForEach<B, FTag, CTag>::Type_t TypeB_t; typedef typename Combine2<TypeA_t, TypeB_t, Op, CTag>::Type_t Type_t; inline static Type_t apply(const BinaryNode<Op, A, B> &expr, const FTag &f, const CTag &c) { // 原有实现完全不变 std::cout << "I don't want to be here. " << std::endl; return Type_t(); } };
修改后你的最小复现用例可以正常编译运行,满足条件时会正确调用你自定义的特化版本,输出I want to get here.。
额外说明
如果你不想修改原生PETE的代码,也可以改用标签分发的方式实现分支选择:在原生特化的apply方法里增加优先级标签参数,将自定义逻辑放到更高优先级的重载函数中,用enable_if控制重载的启用条件,也可以避免修改原有偏特化定义。
内容的提问来源于stack exchange,提问作者ritter
相关产品推荐
相关产品推荐

