问题
I'm writing a pair
wrapper. For the purposes of this question it can be simplified down to:
using namespace std;
template <class T1, class T2>
class myPair {
pair<T1, T2> member;
public:
myPair() = default;
myPair(T1 x, T2 y) : member(make_pair(x, y)) {}
};
I'd like to be able to treat a myPair
as an index-able container of size 2. To do this I'd obviously need to write an index operator for myPair
. I'd like to do something like this, but my return type will depend upon a method parameter, and I can't use method parameters in meta-programming.
auto myPair::operator[](int index) {
static_assert(index >= 0 && index < 2, "Index out of range");
return get<index>(*this);
}
Obviously I could tackle this in the same way that pair
does by providing a get
function, but I'd like to me able to use the index operator syntax. Is there any way I can specialize a function template or use a method parameter to meta-program a template's return type?
回答1:
It's almost possible. The integer literal can't be used directly as a constant-expression, but it can be wrapped in one, for example a template instantiation.
template <int> struct idx_ {};
template <char... C>
auto operator ""_i () {
return idx_<(C - '0')...>{};
}
template <class T1, class T2>
class myPair {
std::pair<T1, T2> member;
public:
myPair() = default;
myPair(T1 x, T2 y) : member(std::make_pair(x, y)) {}
T1 &operator [] (idx_<0>) {
return member.first;
}
T2 &operator [] (idx_<1>) {
return member.second;
}
};
int main() {
myPair<int, std::string> mp(42, "Hi");
std::cout << mp[0_i] << ", " << mp[1_i] << '\n';
}
Output:
42, Hi
Live on Coliru
回答2:
No, it's not possible. The member function operator[]
accepts non-constexpr objects, therefore making a compile time type detection pretty much impossible.
This will also make the static_assert
not compile, for the same reason.
回答3:
You may use std::intergral_constant
template <std::size_t N>
const auto& operator[](std::integral_constant<std::size_t, N>) const {
static_assert(N < 2, "Index out of range");
return std::get<N>(member);
}
template <std::size_t N>
auto& operator[](std::integral_constant<std::size_t, N>) {
static_assert(N < 2, "Index out of range");
return std::get<N>(member);
}
Live Demo
来源:https://stackoverflow.com/questions/31922056/meta-programming-with-a-method-parameter