roniabusayeed
roniabusayeed

Reputation: 93

How to specialize a function template with iterator traits?

template <typename ForwIt>
typename std::iterator_traits<ForwIt>::value_type
foo(ForwIt begin, ForwIt end, double bar)
{
    using value_type = typename std::iterator_traits<ForwIt>::value_type;
    // value_type is the type of the values the iterator ForIt points to

    value_type baz;

    // Do stuff with the values in range [begin, end).
    // And modify baz;
    
    return baz;
}

int main()
{
    std::vector<int> numbers;
    for (int i = 0; i < 10; ++i)
        numbers.push_back(i);
    
    const std::vector<int> v0(numbers.begin(), numbers.end());
    const std::vector<float> v1(numbers.begin(), numbers.end());

    std::cout << foo(v0.begin(), v0.end(), 0.1) << ' ' <<
        foo(v1.begin(), v1.end(), 0.1) << std::endl;

    return 0;
}

Deduction of the return type of foo function is whatever the value_type is is deduced to. Now this works for all numeric types.

But I want the return type (and type of baz) to be double when value_type is deduced integer type. How can I make a specialization in this case?

Upvotes: 0

Views: 241

Answers (1)

cigien
cigien

Reputation: 60208

You can avoid specializations, or writing another overload. Instead, you can use conditional_t to select a specific type according to some condition

// alias for convenience
using T = typename std::iterator_traits<ForwIt>::value_type;

// if T is int, value_type is double, otherwise it's just T
using value_type = std::conditional_t<std::is_same_v<T, int>, double, T>;

For the return type, simply use auto, and the correct type will be deduced from the type of baz.

Here's a demo

Upvotes: 0

Related Questions