If I give
typedef std::vector<int> v;
Then the below can be used to capture the type of the constant iterator (an alternative is to use v::const_iterator
, but this depends on the const_iterator
member type being explicitly defined in the class.
typedef typename std::result_of<decltype(&v::cbegin)(v*)>::type const_iterator;
Indeed, we can check that the above does as we want.
static_assert(std::is_same<const_iterator, typename v::const_iterator>::value);
However, I find a compiler failure on the below.
typedef typename std::result_of<decltype(&v::begin)(v*)>::type iterator;
The compiler complains that the method is overloaded (by const modifier) and cannot be unambiguously resolved. However, I cannot find out the syntax to resolve the ambiguity. At a minimum, one expects the below to be unambiguous, because only the const version can operate on a const object. However, even the below is similarly problematic.
typedef typename std::result_of<decltype(&v::begin)(const v*)>::type const_iterator2;
How do I refer to a particular const or nonconst version of begin?
The following does what you want:
using v = std::vector<int>;
using iter = decltype(std::declval<v>().begin());
static_assert(std::is_same<iter, typename v::iterator>::value);
The issue here is that &v::begin
is ambiguous. There are two v::begin
functions, and the &
operator has no way to know which one to return the address of. Using std::declval
gets around that. Since the return type of std::declval<v>()
is v
, the compiler knows you're interested in the non-const v::begin()
.
Similarly, the following gets you the const version:
using citer = decltype(std::declval<const v>().begin());
static_assert(std::is_same<citer, typename v::contst_iterator>::value);
Note that no objects are created in this code. std::declval
has no definition, so it only works in unevaluated contexts like decltype
.