代码之家  ›  专栏  ›  技术社区  ›  mskfisher KeithS

我如何要求模板函数签名中的常量迭代器语义?

  •  7
  • mskfisher KeithS  · 技术社区  · 15 年前

    我正在创建一个构造函数,它将采用一对输入迭代器。我希望方法签名有编译时间 const 语义类似于:

    DataObject::DataObject(const char *begin, const char *end)
    

    但是,我找不到任何这样的例子。 例如,我的STL实现的范围构造函数 vector 定义为:

    template<class InputIterator>
    vector::vector(InputIterator first, InputIterator last)
    {
        construct(first, last, iterator_category(first));
    }
    

    没有编译时间 常量 保证。 iterator_category / iterator_traits<> 不包含任何与 康斯特 或者。

    有没有什么方法可以保证调用者我不能修改输入数据?

    编辑,2010-02-03 16:35 UTC

    作为如何使用函数的示例,我希望能够传递一对 char* 根据函数签名,指针和知道它们指向的数据不会被修改。
    我希望我能避免创造一对 const char* 保证常量迭代器语义的指针。在这种情况下,我可能被迫支付模板税。

    5 回复  |  直到 7 年前
        1
  •  2
  •   Billy ONeal IS4    15 年前

    您可以简单地创建一个调用模板的虚拟函数 char * const 指针。如果您的模板试图修改它们的目标,那么您的伪函数将不会编译。然后你可以把这个假人放进去 #ifndef NDEBUG 将其从发布版本中排除的保护。

        2
  •  9
  •   sth ACP    15 年前

    调用方可以简单地将模板与常量迭代器一起使用。如果他这样做了,并且编译器没有抱怨,就可以保证函数不会修改数据。如果它将修改数据,则使用常量迭代器实例化模板将导致错误。

    你真的不必 调用方使用const迭代器只是因为您没有修改任何内容。

        3
  •  2
  •   Paolo Tedesco    15 年前

    怎么样

    #include <vector>
    
    template <class T>
    class MyClass{
    public:
        MyClass(typename T::const_iterator t1,typename T::const_iterator t2){
        }
        // *EDITED*: overload for pointers (see comments)
        MyClass(const T* t1,const T* t2){
        }
    };
    
    void main(){
        std::vector<int> v;
        std::vector<int>::const_iterator it1 = v.begin();
        std::vector<int>::const_iterator it2 = v.end();
        MyClass<std::vector<int> > mv(it1,it2);
    
        // with pointers:
        char* c1;
        char* c2;
        MyClass mc(c1,c2);
    }
    
        4
  •  0
  •   Peter Alexander    15 年前

    该向量构造函数正在按值接收其参数,这意味着调用方的迭代器在用于构造函数之前被复制,这当然意味着调用方的迭代器没有发生任何事情。

    const 对于输入参数,只有当通过引用传递时才真正重要。例如

    void foo(int& x)

    VS

    void foo(const int& x)

    在第一个示例中,调用方的输入 x 可以修改为 foo . 在第二个示例中,它可能不是,因为引用是 康斯特 .

        5
  •  0
  •   Manuel    15 年前

    这很容易(但不漂亮),如果你能负担得起提振:

    #include <boost/static_assert.hpp>
    #include <boost/type_traits.hpp>
    
    template<class It>
    void f(It b, It e)
    {
        using namespace boost;
        typedef typename std::iterator_traits<It>::reference reference;
        BOOST_STATIC_ASSERT(is_const<typename remove_reference<reference>::type>::value);
    }
    
    void test()
    {
        f((char const*)0, (char const*)0); // Compiles
        f((char*)0, (char*)0);  // Does not compile
    }
    

    编辑 :如果您希望在签名中包含并指出这一点,则通常会利用模板参数的名称:

    template<class ConstIt>
    void f(ConstIt b, ConstIt e)
    ...