【问题标题】:Specializing the template of std::vector特化 std::vector 的模板
【发布时间】:2017-10-07 21:26:34
【问题描述】:

我试图让 std::vector 保存固定长度的字符串,而不通过包装类引入间接。我的想法是为我的自定义类型专门化std::vector,它在外部表现得像std::vector,但使用它自己的存储布局。有点像std::vector<bool>

我查看了“Extending the namespace std”并没有找到不应该这样做的理由。我能做到以下几点吗?如果不能,我将面临什么样的地狱?

#include <iostream>
#include <vector>

class FixedString {};

namespace std {
    template <>
    class vector<FixedString> {
    public:
        void push_back( FixedString&& value ) {
            std::cout << "Welcome to my vector. Let's play a game!" << std::endl;
        }
    };

    // here be more vector methods.
}

int main () {
    std::vector<int> a;
    a.push_back(int{});

    std::vector<FixedString> b;
    b.push_back(FixedString{});
}

编辑:我知道可能有更好的方法可以做到这一点,并且 cmets 中的讨论帮助我理解了这有什么问题。不过,我想了解这是否合法(即使不受欢迎)C++ 代码。人们在下面暗示了 [namespace.std],但我想了解完全专业化的向量类会违反哪些规则。

【问题讨论】:

  • 我几乎是这么想的。你有任何资源(甚至可能是标准)吗?我的搜索没有结果(或者我只是理解错了)。
  • “固定长度字符串”是什么意思?您是指在编译时长度已知的字符数组吗?此外,如果你真的希望你的向量类像 std::vector 一样工作,你将不得不重载 std::vector 提供的所有方法。
  • @mrks - 查看标准的 [namespace.std] 部分
  • @JorgePerez 它们的长度在编译时是未知的。否则,我会使用 std::array。我知道我必须重载所有方法。
  • 这并不能解释为什么你认为你需要专门化 std::vector。

标签: c++ templates vector stl c++17


【解决方案1】:

[namespace.std] 中的规则是:

只有当声明依赖于用户定义的类型并且特化满足原始模板的标准库要求并且没有明确禁止时,程序才能将任何标准库模板的模板特化添加到命名空间 std。

因此,有两个标准:“取决于用户定义的类型”(一个更好的术语,希望会被采用,是程序定义的类型)和“满足原始模板的标准库要求”。您的示例符合第一个标准但违反了第二个标准,因此它是未定义的行为。

但是,如果您继续填写其余要求(请参阅 [container.requirements][sequence.reqmts][vector])以满足第二个条件,那么就可以了。但值得怀疑。只需编写您自己的容器、最少意外原则等等。当人们看到std::vector&lt;T&gt; 时,他们认为它实际上是std::vectorstd::vector&lt;bool&gt; 已经够糟糕了,不要再添加一个了。

【讨论】:

  • 您是否会说让 MyVector 在默认情况下导入所有 std::vector 方法并专门针对 FixedString 会是更好的方法?
  • @mrks 如果FixedString 是一些特殊的东西,需要它自己的独立容器类型,那似乎你应该需要自己的独立容器类型。
猜你喜欢
  • 2016-11-07
  • 1970-01-01
  • 1970-01-01
  • 2018-04-27
  • 2016-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多