栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ SFINAE 在模板偏特化中增加额外的约束 trait

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ SFINAE 在模板偏特化中增加额外的约束 trait

我们经常需要确定某个类型是否为某个模板的实例,写一个简单的 trait 即可,这里我们使用了一个非常简单的偏特化:

template 
struct A {};

template 
struct is_instantiation_of_A : std::false_type {};

template 
struct is_instantiation_of_A> : std::true_type {};

然而,有时我们希望 在偏特化中 增加额外的约束,例如要求 A 的模板参数 T 须为 trivial 类型,以下 2 种写法都是错误的:

template 
struct is_trivial_instantiation_of_A : std::false_type {}; // 基模板

template >>
struct is_trivial_instantiation_of_A> : std::true_type {}; // 错误

template >>
struct is_trivial_instantiation_of_A> : std::true_type {}; // 错误

注意: 如果不是偏特化上下文,这两种写法都对!

上述第 1 种错误写法的问题很有意思:在这个偏特化中,第 2 个模板参数依赖于第 1 个模板参数 T,而由于 T 处于一个待匹配的偏特化之中,T 依赖于“到底匹配到了哪个偏特化”这个判断,而要完成这个判断,第 2 个模板参数又必须是确定的 —— 此时就形成了模板参数 1 和 2 的相互依赖,类型推断无法完成,这是一种特殊的 非推断上下文。

第 2 种错误写法的问题很明显,偏特化不能具有默认模板参数,因此我们常用的“增加占位模板参数作为开关”的技巧失效了;此外也有与第 1 种一样的错误,这里的模板参数 2 也与模板参数 1 相互依赖。

正确的写法是:

template 
struct is_trivial_instantiation_of_A : std::false_type {}; // 基模板

template 
struct is_trivial_instantiation_of_A<
    A,
    std::enable_if_t> > : std::true_type {}; // 正确

即 在基模板中增加一个有默认值的待定模板参数,它如同一个“插槽”,根据需要可以在特化中引入任何额外的 trait;阅读标准库,可发现这种用法比较常见。

测试(通过编译即可):

int main() {
    static_assert(  is_instantiation_of_A>::value, "");
    static_assert(  is_trivial_instantiation_of_A>::value, "" );
    static_assert( !is_trivial_instantiation_of_A>::value, "" );

    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/917179.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号