C++ 自然禁止C+中的包装类+;

C++ 自然禁止C+中的包装类+;,c++,c++11,C++,C++11,所以,我发现使用集合的算法更自然,而不是使用一对迭代器。我写了一些函数,比如 template <typename R> void sort(R& range) { return std::sort(std::begin(range), std::end(range)); } 模板 无效排序(R&R范围){ 返回std::sort(std::begin(range),std::end(range)); } 为了能够处理我编写的以下包装类集合的一部分,它只包含一对迭

所以,我发现使用集合的算法更自然,而不是使用一对迭代器。我写了一些函数,比如

template <typename R>
void sort(R& range) {
    return std::sort(std::begin(range), std::end(range));
}
模板
无效排序(R&R范围){
返回std::sort(std::begin(range),std::end(range));
}
为了能够处理我编写的以下包装类集合的一部分,它只包含一对迭代器

template <typename T>
class Range{
public:
    Range(T begin, T end): begin_(begin), end_(end) {}

    const T& begin() {
        return begin_;
    }

    const T& end() {
        return end_;
    }


private:
    T begin_, end_;
};
模板
等级范围{
公众:
范围(T begin,T end):开始(begin),结束(end){
常量T&begin(){
返回开始;
}
常数T&end(){
返回端;
}
私人:
T开始,结束;
};
到那一点,一切都很好。现在我想要一个复制/(如果可能的话移动)其参数并返回新集合的函数

我写了这样的东西:

template <typename R>
R sorted(R range) {
    sort(range);
    return std::move(range);
}
模板
R排序(R范围){
排序(范围);
返回标准::移动(范围);
}
这很好,只是如果我调用它时包装器
Range
class内部集合发生了变化。我确实理解,仅使用迭代器类型通常不可能检索集合类型以创建新的集合,但我想至少不允许使用此包装器调用它

我确实理解我可以使用
static\u assert
来检查它是否属于特定的
范围
类,除非我找到更好的方法,否则我会这样做。但我希望以更一般的方式禁止它,这样类似的实现也将无法编译


有什么想法吗?

您可以删除以下功能:

template <typename T>
void sorted(const Range<T>& range) = delete;
模板
已排序无效(常量范围和范围)=删除;
否则,您可以禁止复制和移动对象,因此它只能用于引用

template <typename T>
class Range{
public:
    Range(const Range&) = delete;
    Range(Range&&) = delete;

    Range& operator =(const Range&) = delete;
    Range& operator =(Range&&) = delete;

    // previous code
};
模板
等级范围{
公众:
范围(常数范围&)=删除;
范围(范围&&)=删除;
范围和运算符=(常量范围和)=删除;
范围和运算符=(范围和运算符)=删除;
//先前代码
};

您可以删除以下功能:

template <typename T>
void sorted(const Range<T>& range) = delete;
模板
已排序无效(常量范围和范围)=删除;
否则,您可以禁止复制和移动对象,因此它只能用于引用

template <typename T>
class Range{
public:
    Range(const Range&) = delete;
    Range(Range&&) = delete;

    Range& operator =(const Range&) = delete;
    Range& operator =(Range&&) = delete;

    // previous code
};
模板
等级范围{
公众:
范围(常数范围&)=删除;
范围(范围&&)=删除;
范围和运算符=(常量范围和)=删除;
范围和运算符=(范围和运算符)=删除;
//先前代码
};

我将创建一个名为
owning\u container
的traits类。默认情况下,它考虑作为范围的参数(您应该有一个traits类/concept constepr——如果
begin(x)
在命名空间中使用std::begin;
返回一个迭代器,称之为范围),并拥有一个分配器(另一个trait)(因为不拥有范围通常不需要分配器)以及拥有的C数组和
std::数组
(通过专门化)

这还允许我检测拥有rvalue的容器,并在某些上下文中移动它们的内容(将它们的迭代器更改为
move
iterators),而不必对不拥有rvalue的范围视图执行相同的操作


如上所述,
constexpr
伪概念可能比traits类更好,或者可能有助于扩展它。

我将创建一个名为
owning\u container
的traits类。默认情况下,它考虑作为范围的参数(您应该有一个traits类/concept constepr——如果
begin(x)
在命名空间中使用std::begin;返回一个迭代器,称之为范围),并拥有一个分配器(另一个trait)(因为不拥有范围通常不需要分配器)以及拥有的C数组和
std::数组
(通过专门化)

这还允许我检测拥有rvalue的容器,并在某些上下文中移动它们的内容(将它们的迭代器更改为
move
iterators),而不必对不拥有rvalue的范围视图执行相同的操作


如上所述,
constexpr
伪概念可能比traits类更好,或者可能有助于增强它。

您可以禁止隐式复制您的范围…@Deduplicator,我曾考虑只移动范围,但这对
排序(范围(开始,结束))
没有帮助,因为只需要移动。嗯,您可以在包装器范围中键入定义一个
是包装器
成员,如果该类型存在,则取消排序。。。比只检查特定类的
Range
更一般一些。我尝试过类似的方法,但认为不值得为标准库的使用方式而费心。不过祝你好运。你可以禁止隐式复制你的范围…@Deduplicator,我考虑过只移动范围,但这对排序(范围(开始,结束))没有帮助,因为只需要移动。嗯,您可以在包装器范围中键入定义一个
是包装器
成员,如果该类型存在,则取消排序。。。比只检查特定类的
Range
更一般一些。我尝试过类似的方法,但认为不值得为标准库的使用方式而费心。祝你好运。
std::array
没有分配器。好的,它也不是一个真正的容器。@dyp-yep——通过专门化处理它和C数组。我忘了。
std::array
没有分配器。好的,它也不是一个真正的容器。@dyp-yep——通过专门化处理它和C数组。我忘了。