I have two functions
template <class T> void foo(std::vector<T>* p)
and
template <class T> void foo(std::valarray<T>* p)
The code in the function bodies is identical. Is there a clever way of writing the template so I can avoid the duplication? Something like
template <class T, class Container> void foo(Container<T>* p)
I'm using C 14.
I only want to allow Container
to be either std::vector
or std::valarray
.
CodePudding user response:
Note: you cannot really specialize on std::vector<>
and std::valarray<>
, but you can say, for the given (deduced) T, you expect std::vector<T>
or std::valarray<T>
. Thus aliases will also be resolved.
The trick is, you templetize for a template class C
and a type T
(and possibly further parameters, as in std
), then use std::enable_if<>
that only resolves (to void in this case) when either std::vector<T>
or std::valarray<T>
was resolved.
Also note, you might want to allow custom allocators et. al., i.e., instead of a single T, it's recommended to use typename... Ts
for the container.
#include <iostream>
#include <vector>
#include <valarray>
#include <type_traits>
template<template<class...> class C, typename T>
auto foo(C<T>* arg) -> std::enable_if_t<std::is_same<C<T>, std::vector<T>>::value || std::is_same<C<T>, std::valarray<T>>::value>
{
}
int main() {
std::vector<int> v;
std::valarray<int> va;
//std::pair<int, int> p; // this should fail
foo(&v);
foo(&va);
//foo(&p); // this fails as expected
return 0;
}
CodePudding user response:
You can also create type traits only for your case.
template <typename T>
struct is_vector_or_valarray : std::false_type {};
template<class T>
struct is_vector_or_valarray<std::vector<T>> : std::true_type {};
template<class T>
struct is_vector_or_valarray<std::valarray<T>> : std::true_type {};
template<typename C, typename = std::enable_if_t<is_vector_or_valarray<C>::value>>
void foo(C* p) {}