Interpolated
Interpolated

Reputation: 115

C++, overloding functions, templates

I want to ask is it possible to write overloaded function for arithmetic's type which returns double and for containers (array, vector, valarray, etc...) which returns valarray. Simple example

template<typename T> 
double foo(T x) { 
  return x; 
}
 
template<typename T> 
std::valarray<double> foo(T const &arr) {
  std::valarray<double> valarr(1,1); 
  return valarr; 
}

In result I get expected message: call to 'foo' is ambiguous. Is there any possibility to write such a functions?

I would really appreciate all comments.

Upvotes: 0

Views: 85

Answers (3)

Alan
Alan

Reputation: 1

You can use std::enable_if to do what you want as follows:

#include <iostream>
#include <string>
#include <valarray>

//overload for arthemtic types
template<typename T>
std::enable_if_t<std::is_arithmetic_v<T>, double> foo(T x)
{
    std::cout<<"arithmetic version"<<std::endl;
    return x;
}
//overload for array
template<typename T, std::size_t N>
std::valarray<double> foo(T const (&arr)[N])
{
    std::valarray<double> valarr(2,5); 
    std::cout<<"array version"<<std::endl;
    return valarr;
}

//overload for non-arthemtic types
template<typename T>
std::enable_if_t<!std::is_arithmetic_v<T>, T> foo(T x) //note the "!" in this version
{
    std::cout<<"non-arithmetic version"<<std::endl;
    return x;
}
int main() {
  int arr[3] = {1,2,3};
    foo(arr);//uses array version
    foo(5); //uses arithmetic version
    int p= 0, *c = &p;
    
    foo("string");//uses array version
    foo(p);//uses arithmetic version
    foo(c); //uses non-arithmetic version
} 

The output of the above program can be seen here.

Upvotes: 1

Jarod42
Jarod42

Reputation: 218268

For C-array types, it would be:

template<typename T, std::size_t N>
std::valarray<double> foo(T const (&arr)[N])
{
    // ...
}

Demo

Upvotes: 1

康桓瑋
康桓瑋

Reputation: 43096

You can use C++20 concepts:

#include <valarray>
#include <concepts>

template<typename T> 
  requires std::is_arithmetic_v<T>
double foo(T x) { 
  return x; 
}

template<std::ranges::random_access_range T>
  requires std::is_arithmetic_v<std::ranges::range_value_t<T>>
std::valarray<double> 
foo(T const& arr) {
  std::valarray<double> valarr(1,1); 
  return valarr; 
}

Demo.

Upvotes: 2

Related Questions