2

I am trying to write my own library for competitive programming contests, and I need such code:

#include <functional>
#include <algorithm>

template <typename T>
using binop = std::function<T (T, T)>;

int main()
{
    binop<int> op = std::max<int>;
}

Unfortunately, it produces the following error:

error: conversion from '<unresolved overloaded function type>' to non-scalar type 'binop<int> {aka std::function<int(int, int)>}' requested

But when I remove the line

#include <algorithm>

it magically compiles. (though there shouldn't really be a max function defined)

The question is: how can I compile the code without removing "algorithm"?

Note that I have also tried this:

binop<int> op = (int(*)(int, int)) std::max<int>;

which produces

error: insufficient contextual information to determine type
5
  • 3
    There are multiple std::max overloads. There is one that takes a std::initializer_list Commented Jun 7, 2017 at 18:51
  • I'm aware of that, but why (int(*)(int, int)) std::max<int> doesn't work then? Commented Jun 7, 2017 at 18:53
  • 3
    Try (const int& (*)(const int&, const int&)). That's the actual signature of std::max<int> Commented Jun 7, 2017 at 18:55
  • @VolkovKomm Where do you see that there should be such an overload? My docs show no int(int,int) possible. Commented Jun 7, 2017 at 18:55
  • 1
    Oh, there actually is no int(int, int) overload... And ((const int&(*)(const int&, const int&)) just worked. I guess I'm just stupid, thanks for the explanation. Commented Jun 7, 2017 at 18:58

2 Answers 2

6

This is because there are multiple overloads of the same function. This does not work for exactly the same reason that this does not work

void foo() {}
void foo(int) {}
void foo(double) {}

int main() {
    auto foo_ptr = &foo;
}

To make your code work you would have to cast the function pointer to the right type to tell the compiler which overload you are referring to

#include <algorithm>

template <typename T>
using Func_t = std::function<T(T, T)>;

int main() {
    template <typename T>
    using MaxOverload_t = const T& (*) (const T&, const T&);

    auto f1 = static_cast<MaxOverload_t<int>>(&std::max<int>);
    auto f2 = Func_t<int>{static_cast<MaxOverload_t<int>>(&std::max<int>)};
}
Sign up to request clarification or add additional context in comments.

Comments

3

There are multiple overloads for std::max. Even specifying a template type is not enough as you have

template< class T > 
const T& max( const T& a, const T& b );

//and

template< class T >
T max( std::initializer_list<T> ilist );

The compiler cannot decide which one of those you want.

To get around this we can use a lambda and wrap that around the call to max like

binop<int> op = [](const auto& lhs, const auto& rhs){ return std::max(lhs, rhs); };

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.