2016-06-30 2 views
1

Моей первой попытки использования decltypeконстантный спецификатор к decltype

vector<int> vals; 
const decltype(&vals[0]) ptr; 

for (const auto& val : vals) 
    ptr = &val;  

не компилируется, жалуясь о назначении только для чтения переменной ptr. То, что я пытаюсь достичь, - ptr быть типа const int*. Как я могу заставить его работать? Благодарю.

+0

'сопзЬ Int *' и 'ИНТ * const' разных вещи, как вы можете быть в курсе. –

+0

Вот почему я предпочитаю иметь 'int const *' и 'int * const' (const * always * справа от того, к чему он относится). Это необычно, я знаю, но для себя я хорошо себя чувствую (это не значит, что я тоже не могу прочитать другую версию ...). – Aconcagua

ответ

7

std::vector имеет const_pointer typedef. Вы можете использовать это как

decltype(vals)::const_pointer ptr; 

, чтобы получить правильный указатель константный к типу вектора (Live Example).

+1

Хорошее решение в данном конкретном случае. –

1

Ваше заявление ptr в основном const (int *) ptr, или int * const ptr. Таким образом, указатель является постоянным, а не объектами, на которые он указывает. Вы можете либо сделать valsconst, либо, по крайней мере, направить его на const внутри decltype или использовать typedefs std::vector вместо decltype.

+1

Обратите внимание, что 'std :: as_const' C++ 17 может легко сместить объект в const – KABoissonneault

+0

Не будет ли' as_const' (и 'add_const') влиять на внешний тип, а не на указанный тип? –

+0

'std :: vector :: operator []' возвращает 'const_reference', если вектор сам является' const' (и простой 'reference' в противном случае). Таким образом, адрес 'const_reference' будет' const int * '. – KABoissonneault

3

Просто не объявляйте указатель, прежде чем он вам понадобится. Затем вы можете вывести его тип (в данном случае желаемый const int*) при инициализации.

Это работает:

std::vector<int> val {1,2,3,4}; 

for (const auto &v : val) { 
    auto p = &v; 
    std::cout << *p; 
} 

Это не удается:

std::vector<int> val {1,2,3,4}; 

for (const auto &v : val) { 
    auto p = &v; 
    *p = 7; 
} 
1

typedef не текстуальное замена. decltype не является текстовой заменой. Модификатор const применяется ко всему, к чему он применим, он не достигает внутри результата decltype, чтобы изменить самое левое.

Это будет работать, хотя, потому что теперь const применяется к типу элемента, чтобы сделать тип (const int), а затем ptr сделан указатель на что:

const std::remove_reference<decltype(vals[0])>::type * ptr; 

Заметьте, что это не будет работать, так как он бесцельно пытается const -qualify ссылочного типа:

std::add_pointer<const decltype(vals[0])>::type ptr; 
+0

'decltype (vals [0])' is 'int &'. –

+0

@ T.C .: Хм, и система типов недостаточно умна, чтобы свернуть ее, когда вы пытаетесь сформировать указатель на нее? Мля. –

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