【问题标题】:Detect if a type is a specialization from the primary template or a user-provided specialization检测一个类型是来自主模板的特化还是用户提供的特化
【发布时间】:2021-02-26 22:18:33
【问题描述】:

假设我有这个:

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

现在,预计用户可以将my_template 专门用于他们自己的类型。他们会将这些类型传递给我的一些 API 函数,它们将使用 my_template&lt;T&gt; 的属性来做事。

所以在我的代码中的某个时刻,我有一个my_template&lt;T&gt;。如果my_template&lt;T&gt; 是用户提供的专业化(部分或显式)和false 如果不是.

最明显的解决方案是将私有成员别名或其他一些 concept-detectable 私有声明推入主要的 my_template 定义中,并依赖于用户提供的专业化中不存在的内容。但是,用户可以通过提供适当的定义来伪造明确的专业化。所以这不是万无一失的。

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

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

【问题讨论】:

    标签: c++ c++20


    【解决方案1】:

    最明显的解决方案是将私有成员别名或其他一些可概念检测的私有声明推入主 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 来破坏库。也许反射仍然会给他们提供一种方法(假设这些东西仍然可以访问),但现在他们真的会跳过很多圈子。


    说到反射,当前指定的 API (P1240) 的一部分包括函数 is_specializationis_partial_specializationis_explicit_specialization。如果这些是我认为的意思,那么当我们最终得到反思时,图书馆就不会使用这些魔法基础/魔法成员黑客,而可以直接检查提供的专业化是部分专业化还是显式专业化,或者不是。我认为图书馆应该添加is_primary_specialization 以确保完整性。

    【讨论】:

      猜你喜欢
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-08
      相关资源
      最近更新 更多