А как сейчас правильно константы объявлять?
От: пффф  
Дата: 27.07.24 21:07
Оценка:
Привет

https://godbolt.org/z/jhbda1j6d

#include <cstdint>
#include <deque>

using index_type = std::size_t;
inline constexpr const index_type invalid_index = (index_type)-1;

struct IndicesEntry
{
    index_type i1;
    index_type i2;
};

int main()
{
    std::deque<IndicesEntry> que;
    que.emplace_back(invalid_index, invalid_index);
    //que.emplace_back(IndicesEntry{invalid_index, invalid_index});
}


Выдаёт:
Z:/compilers/msvc/14.41.33923-14.41.33923.0/include\xmemory(700): error C2661: 'IndicesEntry::IndicesEntry': no overloaded function takes 2 arguments
Z:/compilers/msvc/14.41.33923-14.41.33923.0/include\xmemory(700): note: while trying to match the argument list '(const index_type, const index_type)'
Z:/compilers/msvc/14.41.33923-14.41.33923.0/include\xmemory(700): note: the template instantiation context (the oldest one first) is
<source>(16): note: see reference to function template instantiation 'IndicesEntry &std::deque<IndicesEntry,std::allocator<IndicesEntry>>::emplace_back<const index_type&,const index_type&>(const index_type &,const index_type &)' being compiled
Z:/compilers/msvc/14.41.33923-14.41.33923.0/include\deque(1175): note: see reference to function template instantiation 'void std::deque<IndicesEntry,std::allocator<IndicesEntry>>::_Emplace_back_internal<const index_type&,const index_type&>(const index_type &,const index_type &)' being compiled
Z:/compilers/msvc/14.41.33923-14.41.33923.0/include\deque(1139): note: see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<IndicesEntry,const index_type&,const index_type&>(_Alloc &,_Objty *const ,const index_type &,const index_type &)' being compiled
        with
        [
            _Alloc=std::allocator<IndicesEntry>,
            _Objty=IndicesEntry
        ]
Compiler returned: 2

Смущает const index_type&,const index_type& в сообщении об ошибке. Зачем тут ссылки и почему из них оно не может инициализировать объект?

Вот раньше, в C++03 — было понятно — просто нельзя. Но можно было для статик мемберов структур/классов.

А теперь:
inline static const constexpr constinit index_type invalid_index = (index_type)-1;




Кто в теме, не разжуёте для дилетантов?
Re: А как сейчас правильно константы объявлять?
От: andrey.desman  
Дата: 28.07.24 05:07
Оценка: +1
Здравствуйте, пффф, Вы писали:

П>
П>#include <cstdint>
П>#include <deque>

П>using index_type = std::size_t;
П>inline constexpr const index_type invalid_index = (index_type)-1;

П>struct IndicesEntry
П>{
П>    index_type i1;
П>    index_type i2;
П>};

П>int main()
П>{
П>    std::deque<IndicesEntry> que;
П>    que.emplace_back(invalid_index, invalid_index);
П>    //que.emplace_back(IndicesEntry{invalid_index, invalid_index});
П>}
П>

П>Кто в теме, не разжуёте для дилетантов?

Нет конструктора IndicesEntry(index_type, index_type).
Есть конструктор IndicesEntry(const IndicesEntry&);
Ну или IndicesEntry(IndicesEntry&&);
Отредактировано 28.07.2024 5:09 andrey.desman . Предыдущая версия .
Re: А как сейчас правильно константы объявлять?
От: Zhendos  
Дата: 28.07.24 10:22
Оценка: +1
Здравствуйте, пффф, Вы писали:

П>Привет


П>https://godbolt.org/z/jhbda1j6d


П>
П>struct IndicesEntry
П>{
П>    index_type i1;
П>    index_type i2;
П>};
П>    que.emplace_back(invalid_index, invalid_index);
П>


П>


П>Кто в теме, не разжуёте для дилетантов?


Если убрать "inline constexpr" то ошибка останется,
а вот если сменить опцию компилятора на /std:c++20 ,
то все скомпилируется, потому что до C++20 нужно было для
структуры без конструктора использовать "{field1, field2,...}",
а в c++20 разрешили делать вид что у нее есть конструктор.
Re[2]: А как сейчас правильно константы объявлять?
От: пффф  
Дата: 28.07.24 10:43
Оценка:
Здравствуйте, Zhendos, Вы писали:

П>>Кто в теме, не разжуёте для дилетантов?


Z>Если убрать "inline constexpr" то ошибка останется,

Z>а вот если сменить опцию компилятора на /std:c++20 ,
Z>то все скомпилируется, потому что до C++20 нужно было для
Z>структуры без конструктора использовать "{field1, field2,...}",

Я так тоже пробовал:
que.emplace_back({invalid_index, invalid_index});


Выдаёт
<source>(17): error C2672: 'std::deque<IndicesEntry,std::allocator<IndicesEntry>>::emplace_back': no matching overloaded function found
Z:/compilers/msvc/14.41.33923-14.41.33923.0/include\deque(1173): note: could be 'decltype(auto) std::deque<IndicesEntry,std::allocator<IndicesEntry>>::emplace_back(_Valty ...)'
<source>(17): note: 'initializer list': is not a valid template argument for '_Valty'
Compiler returned: 2



Z>а в c++20 разрешили делать вид что у нее есть конструктор.


Ясно. Я пока на 17ом сижу
Re[3]: А как сейчас правильно константы объявлять?
От: Zhendos  
Дата: 02.08.24 08:28
Оценка: +1
Здравствуйте, пффф, Вы писали:

П>Я так тоже пробовал:

П>
П>que.emplace_back({invalid_index, invalid_index});
П>


Нужно указать тип, чтобы компилятор это не путал с 'initializer list':
que.emplace_back(Struct{invalid_index, invalid_index});


Или использовать `push_back`, тем более emplace_back здесь ничего не ускоряет,
так как с "{}" структура будет полностью создана на стеке и только потом передана
в контейнер:
que.push_back({invalid_index, invalid_index});


ну или объявить конструктор у структуры, тогда можно будет
писать как в C++20:

que.emplace_back(invalid_index, invalid_index);
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.