I am not a professional coder and I apologise if my question seams naive or malformed.
I am trying to have a class member function take std::array
or std::vector
in the arguments. Specifically I am passing two arguments that should either both be std::array
or both be std::vector
.
BEFORE trying to make the above work, a minimum set up of what I had was working only with std::vector
arguments. a minimum set up is as follows, where v and p are the ones I desire to have passed as vectors or arrays:
// original version
class my_class_A{
// stuf
};
class my_class_B{
// other stuf
};
class I_am_a_class_of_methods{
public:
inline void my_method(const std::vector<my_class_A> &v,
const std::vector<std::array<uint64_t,2> > &p,
const my_class_B &x,
my_class_B &y){
// `v` and `p` are used to modify `x` and store the result in `y`
return;
};
};
I understand I could do what I want with function overloading, however, I decided I wanted to achieve the desired result with templates
and std::enable_if
, to force me to learn a bit more about them. Well I did learn a lot I didn't know... but not enough it seams. I have basically tried setting up a trait is_both_array_or_vector
, and std::enable_if
will check to see if the template call matches the trait. The final thing I tried is the following, which did compile, but it will only work for std::vector
:
// current version
class my_class_A{
// stuf
};
class my_class_B{
// other stuf
};
// set up a type trait to check if both are vector or both are array
template <typename T1, typename T2>
struct is_both_array_or_vector{
enum { value = false };
};
template <typename T1, typename T2, typename A1, typename A2 >
struct is_both_array_or_vector<std::vector<T1, A1>, std::vector<T2, A2> > {
enum { value = true };
};
template <typename T1, typename T2, size_t D>
struct is_both_array_or_vector<std::array<T1, D>, std::array<T2, D> > {
enum { value = true };
};
// conditionally compile with enable_if
class I_am_a_class_of_methods{
public:
template<template<typename,typename> U, template<typename,typename> S,
typename Au, typename As>
typename std::enable_if<is_both_array_or_vector<U<my_class_A, Au>, S<std::array<uint64_t,2>,As> >::value >::type
my_method(const U<my_class_A, Au> &v,
const S<std::array<uint64_t,2>, As> &p,
const my_class_B &x,
my_class_B &y){
// `v` and `p` are used to modify `x` and store the result in `y`
return;
};
};
When I compile with std::vector
call from main everything works fine. This (of course) doesn't compile with std::array
call (compiler of course complains).
If only I could make template arguments As
and Au
be able to be interpreted as size_t
, then the template would find a match with an std::array
call. This doesn't seam possible however, since I can have either typename
or size_t
, not both as far as I know. Thus my question is, how would I get enable_if to work in this circumstance?
Update: As Javier said, you can keep a private function template that will handle the general case, and overload two methods for the types you want and pass them to that template.
class I_am_a_class_of_methods {
private:
template <typename C1, typename C2>
void my_method_priv(const C1& v, const C2& p, const my_class_B& x, my_class_B& y) {
// ...
}
public:
void my_method(const std::vector<my_class_A>& v,
const std::vector<array<uint64_t, 2>>& p,
const my_class_B& x,
my_class_B& y)
{ my_method_priv(v, p, x, y); }
template <size_t N1, size_t N2>
void my_method(const std::array<my_class_A, N1>& v,
const std::array<std::array<uint64_t, 2>, N2>& p,
const my_class_B& x,
my_class_B& y)
{ my_method_priv(v, p, x, y); }
};
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments