I'm currently writing an iterator for a custom collection-style class. I had a mutable iterator class that worked perfectly, but decided it would be best to also implement a const version that would block modifications of the object whose contents are being iterated. I decided to avoid a separate class and code repetition by using a suggestion I found online to use conditional typing.
I defined the iterator_traits
typealiases in the typical C++11 fashion that would allow code-sharing and template argument-dependent const or mutable behavior (ItemType is a template parameter on the outer container class):
template<bool Const = false>
class iterator {
public:
using reference = std::conditional_t<Const, const ItemType &, ItemType &>;
using pointer = std::conditional_t<Const, const ItemType *, ItemType *>;
//Rest of the iterator_traits and some other typealiases
...
template<bool _Const = Const>
std::enable_if_t<_Const, value_type>
operator*() const
{
//Return copy
}
//Non-const version
template<bool _Const = Const>
std::enable_if_t<!_Const, reference>
operator*()
{
//Return modifiable reference type
}
...
}
I decided to try to remove the repetitive std::conditional_t
calls by creating another template typealias like this:
template<typename type>
using const_conditional = std::conditional_t<Const, const type, type>;
and replacing all the std::conditional_t<...>
with const_conditional<some_type_here>
. This seems to work universally for the outer class template parameter ItemType
type, but not for the outer class type itself when its type is a reference, as in const_conditional<MyCollection<ItemType> &>
. Upon compiling, the compiler complains that I am discarding qualifiers, meaning the const
isn't being applied, so I'm therefore breaking const requirements, yet replacing my custom typealias with the original std::conditional_t
code compiles and works just as expected, and I have no clue why.
I can of course simply go back to using the std::conditional_t
calls I was using originally, which worked fine, but they seemed bloated and repetitive, and I don't understand why my custom typealias fails. Searches across the internet failed to help me in my specific situation. Any help would be very sincerely appreciated.
ItemType&
and ItemType*
are types themselves, and so adding a const qualifier yields ItemType& const
(in which case const
is silently ignored as a result of template argument substitution) and ItemType* const
, respectively, which is different than expected const ItemType&
and const ItemType*
. For the latter, you could use:
template <typename type>
using const_conditional = std::conditional_t<Const, const type, type>;
// ...
using reference = const_conditional<ItemType>&;
using pointer = const_conditional<ItemType>*;
As a side note, _Const
is a reserved identifier, as all other that start with an underscore followed by an uppercase letter.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.