【问题标题】:Circumventing template specialization规避模板专业化
【发布时间】:2011-09-23 20:22:24
【问题描述】:

假设我是某个模板库 (CTL) 的用户,该模板库定义了一个模板,例如,Hector

template <class T>
class Hector {...};

在其文档中,它提供了许多关于Hector 模板行为的保证。 但随后它也为特定类型定义了一个特化Cool

template <>
class Hector<Cool> {....};

专门化的目的是对Hector 进行更优化的实现,但不幸的是,由于这种优化,许多Hector 的保证被违反了。

目前我真的不需要优化,我宁愿保留Hector的所有保证。有什么办法可以在不更改库代码的情况下(CTL 是一个非常受人尊敬的库,你知道的)绕过专业化?有什么办法吗?也许写某种包装?任何事物?我只想让编译器以正常、非优化的方式为Hector&lt;Cool&gt; 生成代码,并提供所有保证。

【问题讨论】:

  • 包装类struct Stool : public Cool { };怎么样,然后使用Hector&lt;Stool&gt;
  • 没有 CTL 这样的东西。有一个库,它起源于几年前写的一些 CTL。
  • +1 纯属欢闹。
  • 其实class Hector还有一个额外的模板参数Allevator。 ;)
  • @Xeo: ITYM Alligator.

标签: c++ templates template-specialization


【解决方案1】:

您是否可以使用没有不需要的专业化的相关模板Reque?否则,我认为您需要为 Cool 创建一个包装器,以便不使用专业化。

【讨论】:

  • 我想发这个,忘记了,现在想起来了。 :(
【解决方案2】:

您可以将cool 包装在一个虚拟类型中以防止模板对其进行专门化。

【讨论】:

    【解决方案3】:

    没有。即使它可以以某种深奥的方式完成,也不要这样做。绕过语言功能应该会触发警报。

    您必须包装该值或使用不同的类型,例如 char 而不是 bool(它们的行为相似),提供 std::vector&lt;char&gt; 而不是 std::vector&lt;bool&gt;

    【讨论】:

    • 谁提到了性病和病媒?
    • AFAIK 文档不能保证 Cool 和 Shar 的大小相同,是吗?
    • @Armen :Cool 有可能大于Shar 但不会更小,Shar 保证能够保存Cool 的所有明确定义的值。跨度>
    • @Armen:正确,Cool 可以有任何大小,不一定是 1,但 Shar 肯定有 1 的大小。也就是说,您可以做一些魔术(也许是特定于实现的)来选择与Cool 大小相同的非Cool 整数类型。
    • 我越想这个问题,我就越觉得这是正确的答案。毕竟,如果您希望vector&lt;bool&gt; 表现得“正确”,那么您必须愿意获取元素的地址(毕竟,您没有准确地告诉您对 Ctd::Hector 的期望)。因此,使用另一种整数类型真的很有意义(并且将具有与 bool 相同的语义,这与其他人建议使用包装器的解决方案相反)。好消息是您甚至可以选择实现的大小。
    【解决方案4】:

    这是一个通用的伪装器:

    template <typename T>
    struct Drool
    {
      Drool(T d) : b(d) { }
      inline operator T() const { return b; }
      inline Drool<T> & operator=(T d) { b = d; return *this; }
    private:
      T b;
    };
    

    现在你可以说Hector&lt;Drool&lt;Cool&gt;&gt;


    根据 Xeo 改进的版本:

    template <typename T>
    struct Drool
    {
      Drool(const T & d) : b(d) { }
      Drool(Drool && o) = default;
    
      inline operator const T & () const { return b; }
      inline operator       T & ()       { return b; }
    
    private:
      T b;
    };
    

    【讨论】:

    • 可以通过将参数作为 const-refs 并为 C++0x 添加一个 move-ctor 来变得更加通用,但除此之外,是的。此外,不需要operator=,因为这是隐式定义的。
    • @Kerrek:另外,应该是operator T&amp;()operator T const&amp;() const。 :)
    • @Xeo:我其实很想知道——强制转换的结果可以是左值吗?
    • @Xeo: 嗯,好的,如果我有Drool&lt;T&gt; x; T y; 并且我说x = y;,这已经调用了x = Drool&lt;T&gt;(y);,那么在什么时候演员会作为左值有用?
    【解决方案5】:
    1. 打开标准某些实现
    2. Ctrl+A
    3. Ctrl+C
    4. 创建一个名为"my_hector.h" 的新文件
    5. Ctrl+V
    6. 删除专业化
    7. 搜索#include &lt;hector&gt;并将其替换为#include "my_hector.h"
      [编辑@Xeo ;-) ]​​i>
    8. 重命名以两个前导下划线后跟一个小写字母开头的标识符,以及以一个前导下划线后跟一个大写字母开头的所有标识符。

    【讨论】:

    • 我喜欢这个解决方案,其实 :) 为什么不呢?
    • 我不喜欢这个解决方案,因为它放弃了便携性。
    • @Armen:我从没说过标准... /nonchalant
    • @Xaade:嗯,编写自己的代码如何等同于更改其他代码?
    • 如果您未能在 所有 间接包含的头文件中将 hector 替换为 my_hector.h,也有可能破坏 ODR。所以不要这样做。绝不。至少不是我正在做的项目。我希望我能多次对此投反对票。
    猜你喜欢
    • 1970-01-01
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    • 2015-08-01
    相关资源
    最近更新 更多