Reputation: 11677
Here's my example:
template<typename TContainer>
class MyClass
{
public:
typedef typename SomeUnknownHelper<TContainer>::iterator iterator;
};
std::vector<int>::iterator i = MyClass<std::vector<int>>::iterator;
int *pi = MyClass<int[20]>::iterator;
Basically, I don't know how to write SomeUnknownHelper
.
I know I could specialize MyClass
itself, but in my real-world case it would be a hassle because the class is large.
Upvotes: 2
Views: 357
Reputation: 131809
That's easily doable with decltype
and std::begin
:
#include <iterator>
#include <utility>
namespace tricks{
using std::begin; // fallback for ADL
template<class C>
auto adl_begin(C& c) -> decltype(begin(c)); // undefined, not needed
template<class C>
auto adl_begin(C const& c) -> decltype(begin(c)); // undefined, not needed
}
template<typename TContainer>
class MyClass
{
public:
typedef decltype(tricks::adl_begin(std::declval<TContainer>())) iterator;
};
std::vector<int>::iterator i = MyClass<std::vector<int>>::iterator;
int *pi = MyClass<int[20]>::iterator;
An even better option might be using Boost.Range:
#include <boost/range/metafunctions.hpp>
template<typename TContainer>
class MyClass
{
public:
typedef typename boost::range_iterator<TContainer>::type iterator;
};
std::vector<int>::iterator i = MyClass<std::vector<int>>::iterator;
int *pi = MyClass<int[20]>::iterator;
Upvotes: 2
Reputation: 477160
That's only one single specialization, how bad could that be?
template <typename T> struct ContainerTrait
{
typedef typename T::iterator iterator;
typedef typename T::const_iterator const_iterator;
};
template <typename T, unsigned int N> struct ContainerTrait<T[N]>
{
typedef T * iterator;
typedef T const * const_iterator;
};
Alternatively, you can use the free std::begin
/std::end
and auto
:
auto it = std::begin(x); // x could be vector<int> or float[10]...
Upvotes: 1