Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accept both int and class in variadic templated function?

Wrestling templates for this one function is proving to be beyond me.


What I want:

A function that produces the same float type as the one given to it inside any of the following containers:

  • vector<ANY_FLOAT_TYPE>
  • array<ANY_FLOAT_TYPE, N>

(I'm open to having it accept even more containers, of course!)


The Problem:

The problem lies with array<> accepting an integer as its second template argument while vector<> accepts an allocator in that position. How do I write a templated function that can accept both typenames and ints for a single argument? Or is this the wrong way to proceed and write this function?

I could just copy-paste and write the function twice, both for vector<>s and array<>s, but that's no solution...

template <typename FT, typename CONT_T, typename... Ts>
FT float_sum( CONT_T<FT, Ts...> xs ) {

    // WARNING: not an accurate summation algorithm!
    return accumulate( xs.begin(), xs.end(), 0 );

    //////////////
    static_assert( is_floating_point<FT>::value, "sum() only accepts floating point types." );
}
like image 640
Xunie Avatar asked Mar 23 '26 09:03

Xunie


1 Answers

Just take the entire container as a template parameter and instead use value_type, which is part of the interface for all Container types. Something like

template <typename Container>
auto sum(Container const &container)
    -> typename Container::value_type
{
  using value_type = typename Container::value_type;
  static_assert(std::is_floating_point<value_type>::value, 
                "only for floating types");

  return std::accumulate(container.cbegin(), container.cend(), value_type{});
}

Also, if you decide you eventually also want to sum containers with non-floating types using some other specialization, you may opt to drop the static assertion in favor of SFINAE with std::enable_if, or (by C++20) Concepts. With the Concepts TS available in GCC >= 6:

template <typename Container>
auto sum(Container const &container)
requires 
    std::is_floating_point<typename Container::value_type>::value    
{
  using value_type = typename Container::value_type;
  return std::accumulate(container.cbegin(), container.cend(), value_type{});  
}
like image 165
miradulo Avatar answered Mar 25 '26 22:03

miradulo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!