I have made a type-safe ID class, but now I want to support operator++ if the underlying type also has it. From this and this answears I have come up with 2 alternatives, but they both fail when instantiated with AId:
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) {}
...
//This fails with error: no match for 'operator++' (operand type is
//'AId<some_type, std::basic_string<char> >::value_type
//{aka std::basic_string<char>}')
//auto operator++() -> decltype(++id, std::ref(type())) { ++id; return *this; }
// ^
template<typename = decltype(++id)>
auto operator++() -> decltype(++id, std::ref(type())) { ++id; return *this; }
//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 can AId<>
have operator++
only if AId<>::value_type
also has it? I'm limited to c++11 and no boost.
Previously there was a second question from which I have made a question on its own here.
Although I'm actually using @Sam Varshavchik answear in my code, I consider the one provided by @Guillaume Racicot to be more general, so I chose that as a solution.
I'm now using @Barry's answear which is both simple and correct.