Как я требую const_iterator семантики в шаблонной подписи функции?

Я создаю конструктора, который возьмет пару входных итераторов. Я хочу, чтобы сигнатура метода имела время компиляции 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));
}

который не имеет никакого времени компиляции const гарантии. iterator_category / iterator_traits<> не содержите ничего касающегося const, также.

Там какой-либо путь состоит в том, чтобы указать, чтобы гарантировать вызывающей стороне, что я не могу изменить входные данные?

редактирование, 03.02.2010 16:35 UTC

Как пример того, как я хотел бы использовать функцию, я хотел бы смочь передать пару char* указатели и знают, на основе функциональной подписи, что данные указывают по желанию не быть измененными.
Я надеялся, что мог постараться не создавать пару const char* указатели для гарантии const_iterator семантики. Я могу быть вынужден заплатить шаблонный налог в этом случае.

7
задан mskfisher 25 May 2017 в 19:59
поделиться

5 ответов

Вы можете просто создать фиктивную функцию, которая вызывает ваш шаблон с указателями char * const . Если ваш шаблон пытается изменить свои цели, ваша фиктивная функция не будет компилироваться. Затем вы можете поместить указанный манекен внутрь #ifndef NDEBUG охранников, чтобы исключить его из сборок выпуска.

2
ответ дан 6 December 2019 в 19:36
поделиться

Вызывающий может просто использовать шаблон с константными итераторами. Если он это делает, а компилятор не жалуется, гарантируется, что функция не изменяет данные. Если он изменит данные, создание экземпляра шаблона с помощью константного итератора приведет к ошибкам.

На самом деле вам не нужно заставлять вызывающую программу использовать константные итераторы только потому, что вы ничего не изменяете.

9
ответ дан 6 December 2019 в 19:36
поделиться

А как насчет

#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);
}
2
ответ дан 6 December 2019 в 19:36
поделиться

Этот конструктор вектора получает свои аргументы по значению, что означает, что итераторы вызывающего объекта копируются перед использованием в конструкторе, что, конечно же, означает, что ничего не происходит итераторам вызывающего.

const для входных аргументов имеет значение только при передаче по ссылке. например

void foo (int & x)

vs

void foo (const int & x)

В первом примере ввод вызывающей стороны для x может быть изменен с помощью foo . Во втором примере это может быть не так, поскольку ссылка const .

0
ответ дан 6 December 2019 в 19:36
поделиться

Это легко (но не красиво), если вы можете позволить себе повышение:

#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)
...
0
ответ дан 6 December 2019 в 19:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: