Is there any nice way to do the following?
/* vvv */
template<typename Wrapper> using T = typename Wrapper::type
T f(const T &a, const T &b) {
return a b;
}
where Wrapper
is some class which contains (several) types defined inside of it.
I can do the following, but I don't like this approach as it makes the function have several templated types (and also does not have the exact same meaning):
template<typename Wrapper, typename T = typename Wrapper::type>
T f(..)
I want to do this purely to reduce boilerplate of typing typename Wrapper::type
in the function declaration. If there is a better way to do this, please let me know.
Note: in my project the Wrapper
type needs to satisfy some concept, which also requires having the type type
defined inside the type Wrapper
.
If it may help, here is my use case. I am (attempting) to write a linear algebra library. In this scenario, in order to create objects such as vectors or matrices, we need to supply a field F, which must satisfy:
- F is over some elementary type T (available by e.g.,
F::type
) - F is supplied with two operations
OpAdd
andOpMul
, both of which can operate onT
.
Defining this using concepts is simple, however this adds some clutter, such as my example above.
CodePudding user response:
Do you know what the type will be? If so you can supply the template argument:
template<class T>
using inner = typename T::type;
template<class T>
inner<T> f(inner<T> const& a, inner<T> const& b);
// ...
f<X>(y, y);
CodePudding user response:
In requested circumstances, what you don't like is the only solution
#include <type_traits>
template<typename Wrapper,
typename T = typename Wrapper::type,
typename std::enable_if<std::is_same<T, typename Wrapper::type>::value>::type* = nullptr>
T f(const T &a, const T &b) {
return a b;
}
struct S {
typedef long type;
};
int main() {
f<S>(0L, 0L); // ok
// f<S>(0, 0); // failure
// If the second type is set explicitly
f<S, long>(0L, 0L); // ok
f<S, long>(0, 0); // ok
// f<S, int>(0L, 0L); // failure
// f<S, int>(0, 0); // failure
}
This is a better solution than one with inner<T>
, because f<S>(0, 0)
will not fail with inner<T>
- the exact long
is required but int
is passed.