检测类型是来自主模板的专门化还是用户提供的专门化 [英] Detect if a type is a specialization from the primary template or a user-provided specialization

查看:13
本文介绍了检测类型是来自主模板的专门化还是用户提供的专门化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有这个:

template<typename T>
class my_template {...};

现在,用户可以针对自己的类型专门化my_template。它们会将这些类型传递给我的一些API函数,这些API函数将使用my_template<T>的属性进行操作。

所以在我的代码中的某个点上,我有一个my_template<T>。我想要某种类型的元函数,如果my_template<T>是用户提供的专门化(部分或显式),则接受my_template<T>并生成编译时值true,如果不是,则false

最明显的解决方案是将私有成员别名或其他concept可检测的私有声明添加到主my_template定义中,并依赖于用户提供的专门化中不存在的成员别名。但是,用户可以通过提供适当的定义来伪造明确的专门化。所以这并不是万无一失的。

这个问题不是诡辩。C++20规范有一个元函数ITER_CONCEPT(I),根据std::iterator_traits<I>是来自主模板还是来自用户提供的专门化,该元函数具有不同的内部行为。当然,作为标准库,它们可以创建一个前缀为__的标识符作为主模板的成员,从而将来自用户空间的任何企图伪造声明为未定义的行为。

只有编译器/标准库实现才能万无一失地做到这一点,还是在C++20中可以做到这一点?

推荐答案

最明显的解决方案是将私有成员别名或其他一些可检测到概念的私有声明添加到主要的MY_TEMPLATE定义中,并依赖于用户提供的专门化中没有的成员别名。但是,用户可以通过提供适当的定义来伪造明确的专门化。所以这并不是万无一失的。

基本上就是这样,是的。例如,libstdc++的迭代器特征使其主类模板继承自隐藏的基类模板,然后检查从该基类继承。

是的,用户可以通过提供适当的定义来打造显式的专门化--但就像这样做。这不是你会偶然做的事情,这显然是毫无意义的恶意行为,典型的说法是,库和语言抵御的是墨菲,而不是马基雅维利。

使用模块,您可以通过导出主模板但不实际导出用于检查类模板是否专门化的基类来使用户更难显式恶意:

export module std;

namespace std {
    template <typename T> struct __iterator_traits { };

    template <typename T>
    export struct iterator_traits : __iterator_traits { };
}
现在,用户甚至无法命名std::__iterator_traits来拆分库。也许反思仍然会给他们提供一种方法来做到这一点(假设这些东西仍然可以访问),但现在他们真的会经历很多困难。


说到反射,当前指定的接口(P1240)的一部分包括函数is_specializationis_partial_specializationis_explicit_specialization。如果这些都是我认为它们的意思,那么当我们最终得到反射时,库就不必使用这些魔法库/魔术成员黑客,而只需直接检查所提供的专门化是部分专门化还是显式专门化。我认为为了完整性,库可能应该添加is_primary_specialization

这篇关于检测类型是来自主模板的专门化还是用户提供的专门化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆