Reputation: 43
you helped me before so here I am again with another question in hope for an answer.
I have a function that processes a range of std::complex<float>
values. My initial attempt of a function definition was
// Example 1
using namespace std; // not in original code
Errc const& process(vector<complex<float>>::iterator begin, vector<complex<float>>::iterator end);
This however only works for vectors, not C-style arrays, std::arrays, ranges, etc.
After some fiddling, lots of Google and a little bit of luck, I managed to construct this:
// Example 2
using namespace std; // not in original code
template<
template<typename T> class C,
typename T,
typename C<T>::iterator iterator
>
Errc const& process(typename C<T>::iterator begin, typename C<T>::iterator end);
I am not even sure if that works but it compiles at least. What I think it does, is define a function that processes any container with an arbitrary value type. This would be a problem, as I can only process std::complex (or maybe similar complex floating point values) but not std::string for example.
What I would like to do:
// Example 3
using namespace std; // not in original code
template<
template<typename complex<float>> class C,
typename C<complex<float>>::iterator iterator
>
Errc const& process(typename C<complex<float>>::iterator begin, typename C<complex<float>>::iterator end);
But this apparently is not the way to do this. I am about 60% percent sure I also messed something up in example 2.
Any help or hints are greatly appreciated. Thank you
Upvotes: 1
Views: 499
Reputation: 217275
Your example 2 is nearly correct
template<
template<typename T> class C,
typename T,
typename C<T>::iterator iterator // That is wrong
>
Errc const& process(typename C<T>::iterator begin, typename C<T>::iterator end);
it should be:
template<template <typename> class C, typename T>
Errc const& process(typename C<T>::iterator begin, typename C<T>::iterator end);
But issue is that C
/T
are not deducible, and you have to call it like:
process<std::vector, std::complex<float>>(v.begin(), v.end());
And C-array
and std::array
doesn't match template <typename> class C
neither (and std::vector
has default allocator too :-/)
Simpler would just be
template<typename Iterator>
Errc const& process(Iterator begin, Iterator end);
possibly with some SFINAE
template <typename Iterator,
std::enable_if_t<std::is_same_v<std::complex<float>,
std::iterator_traits<Iterator>::value_type>, int> = 0>
Errc const& process(Iterator begin, Iterator end);
or C++20 requires:
template <typename Iterator>
Errc const& process(Iterator begin, Iterator end)
requires (std::is_same_v<std::complex<float>, std::iterator_traits<Iterator>::value_type);
If you want only contiguous sequences, you might use std::span
Errc const& process(std::span<std::complex<float>)
Upvotes: 3
Reputation: 117298
You could use std::iterator_traits
and compare the value_type
of the iterator with the type you'd like to support:
#include <iterator>
#include <type_traits>
template<class It, std::enable_if_t<
std::is_same_v<class std::iterator_traits<It>::value_type,
std::complex<float>
>, int> = 0>
Errc const& process(It begin, It end) {
//...
}
Alternative:
template<class It>
std::enable_if_t<std::is_same_v<class std::iterator_traits<It>::value_type,
std::complex<float>>, Errc const&>
process(It begin, It end) {
//...
}
If SFINAE is not needed, static_assert
:
template<class It>
Errc const& process(It begin, It end) {
static_assert(
std::is_same_v<class std::iterator_traits<It>::value_type,
std::complex<float>>);
//...
}
Upvotes: 2