While attempting to solve this (un)problem, I noticed a very strange behaviour which in short made possible that a bool
is false and its !
(not value) is also false. I would like to know how this is possible. The code that causes this follows:
template<typename T, typename TID = unsigned int>
struct AId {
typedef AId<T, TID> type;
typedef T handled_type;
typedef TID value_type;
private:
value_type id;
template<typename _T> struct IsIncrementable
{
template<typename _U> using rm_ref = typename std::remove_reference<_U>::type;
typedef char (&yes)[1];
typedef char (&no)[2];
template<class _U>
static yes test(_U *data, typename std::enable_if<
std::is_same<_U, rm_ref<decltype(++(*data))>>::value
>::type * = 0);
static no test(...);
static const bool value = sizeof(yes) == sizeof(test((rm_ref<_T> *)0));
};
public:
explicit AId(const value_type &id) : id(id) {}
...
//IsIncrementable<value_type>::value is false:
//error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename std::enable_if<IsIncrementable<value_type>::value, int>::type = 0>
type operator++(int /*postfix*/) { type old(id); ++id; return old; }
//!IsIncrementable<value_type>::value is also false:
//error: no type named 'type' in 'struct std::enable_if<false, int>'
template<typename std::enable_if<!IsIncrementable<value_type>::value, int>::type = 0>
type operator++(int /*postfix*/) { type old(id); ++id; return old; }
};
How is it possible that IsIncrementable<value_type>::value
is false and !IsIncrementable<value_type>::value
is also false?