假设我有这个:
template<typename T>
class my_template {...};
现在,用户预计能够专业化my_template
对于他们自己的类型。他们会将这些类型传递给我的一些 API 函数,这些函数将使用my_template<T>
做事。
所以在我的代码中的某个时刻,我有一个my_template<T>
。我想要某种元函数,它需要my_template<T>
并导致编译时值true
if my_template<T>
是用户提供的专业化(部分或显式)并且false
如果不是的话。
最明显的解决方案是推送私有成员别名或其他一些concept
-可检测的私有声明,进入主要my_template
定义,并依赖于用户提供的专业化中不存在的内容。然而,用户可以通过提供适当的定义来建立明确的专业化。所以这并不是万无一失的。
这个问题并不是诡辩。 C++20 规范有一个元函数ITER_CONCEPT(I)
,根据是否有不同的内部行为std::iterator_traits<I>
来自主模板或用户提供的专业化。当然,作为标准库,他们可以创建一个前缀为的标识符__
作为主模板的成员,从而声明任何从用户空间尝试的伪造行为都是未定义的行为。
这是只有编译器/标准库实现才能做到万无一失的事情,还是可以在 C++20 中做到这一点?
最明显的解决方案是将私有成员别名或其他一些概念可检测的私有声明推入主 my_template 定义中,并依赖于用户提供的专业化中不存在的情况。然而,用户可以通过提供适当的定义来建立明确的专业化。所以这并不是万无一失的。
基本上就是这样,是的。例如,libstdc++ 的迭代器特征使其主类模板继承自隐藏的基类模板,然后检查是否从该基类模板继承。
是的,一个用户could通过提供适当的定义来形成明确的专业化 - 但是,就像,不要这样做。这不是你偶然会做的事情,这是明显且毫无意义的恶意,典型的说法是图书馆和语言防御的是墨菲,而不是马基雅维利。
使用模块,您可以通过导出主模板但实际上不导出用于检查类模板是否专用的基类来使用户更难明显恶意:
export module std;
namespace std {
template <typename T> struct __iterator_traits { };
template <typename T>
export struct iterator_traits : __iterator_traits { };
}
现在用户甚至无法命名std::__iterator_traits
为了破坏图书馆。也许反思仍然会给他们一种方法来做到这一点(假设这些东西仍然可以访问),但现在他们会really跳过很多圈子。
说到反射,当前指定的 API 的一部分(P1240) 包括函数is_specialization
, is_partial_specialization
, and is_explicit_specialization
。如果这些意味着我认为他们的意思,那么当我们最终得到反思时,那么库就不会使用这些魔法基础/魔法成员黑客,而可以直接检查所提供的专业化是否是部分或显式专业化或不是。我认为图书馆应该添加is_primary_specialization
为了完整性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)