2016-03-11 2 views
2

У меня есть простая структура данных, которая называется array (аналогично std :: array). array класс есть способ называется all(). Вот объявление методов:Корректность верности в C++

const range<const_type_pointer> all() const; 
range<type_point> all(); 

range является шаблоном класса, который строится на два итераторов. Вот упрощенная версия range объявление класса:

template <typename Iterator> 
class range { 

    typedef typename iterator_traits<Iterator>::type_value type_value; 
    typedef typename iterator_traits<Iterator>::type_reference type_reference; 
    typedef typename iterator_traits<Iterator>::type_pointer; 

    range(Iterator begin, Iterator end); 
// methods & algorithms 

// data members 

    mutable Iterator _begin; 
    mutable Iterator _end; 
}; 

Так в основном, если я вызываю метод все на const array объекте, он должен вызвать const перегрузки методы и возврат const range. Теперь в моем алгоритмах разделе, у меня есть простой алгоритм со следующей подписью:

template <typename UnaryFunction> 
    range forEach(UnaryFunction function); 

Затем я попробовал следующее испытание:

void test1(const array<int, 10>& array) 
{ 
    auto r = array.all(); 
    r.forEach([](int i) { std::cout << i << " "; }); 
} 

И второй:

void test2(const array<int, 10>& array) 
{ 
    auto r = array.all(); 
    r.forEach([](int& i) { ++i; }); 
} 

В первом случае, где я просто печатал переменную i, компилятор не жаловался, хотя я назвал метод const range на объекте const range. Во втором случае компилятор жаловался. Является ли это поведение стандартным confornant?

Как компилятор, я использую компилятор MSVS.

+1

как примечание стороны: не возвращайте 'const T' (без ссылки). Он вызывает тонкие ошибки и ничего не решает. В вашем случае return 'range ' – bolov

+0

так, например, r.forEach ([] (int i) {std :: cout << i << "";}); не будет работать? Считаете ли вы, что лучше решать разные классы (range & const_range)? –

ответ

1

Первый. Sice вы возвращаетесь по стоимости, на самом деле это не имеет никакого значения, если вы возвращаете const range или range.

Второй. auto r = array.all(); создает копию того, что было возвращено all. Ваш r является неконстантным объектом, а используется неконстантный forEach. Но так как итератор const во второй версии, вы не можете изменить итерабельность.

1

auto работает так же, как шаблон аргумента дедукции, что означает, что она падает ссылки верхнего уровня и верхнего уровня const & volatile Отборочные. Другими словами, ваш r имеет тип range<const_pointer_type> в обоих случаях.

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

Обычно вы должны просто возвращать объекты без cv-квалификаторов. Он будет играть лучше с семантикой перемещения и не приведет к неправильным ожиданиям.

Смежные вопросы