Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 4608040
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T00:47:18+00:00 2026-05-22T00:47:18+00:00

Given the following code, what is the reason behind the ambiguity? Can I circumvent

  • 0

Given the following code, what is the reason behind the ambiguity? Can I circumvent it or will I have to keep the (annoying) explicit casts?

#include <functional>

using namespace std;

int a(const function<int ()>& f)
{
    return f();
}

int a(const function<int (int)>& f)
{
    return f(0);
}

int x() { return 22; }

int y(int) { return 44; }

int main()
{
    a(x);  // Call is ambiguous.
    a(y);  // Call is ambiguous.

    a((function<int ()>)x);    // Works.
    a((function<int (int)>)y); // Works.

    return 0;
}

Interestingly, if I comment out the a() function with the function<int ()> parameter and call a(x) in my main, the compilation correctly fails because of the type mismatch between x and the argument function<int (int)> of the only a() function available. If the compiler fails in that case, why would there be any ambiguity when the two a() functions are present?

I’ve tried with VS2010 and g++ v. 4.5. Both give me the exact same ambiguity.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T00:47:19+00:00Added an answer on May 22, 2026 at 12:47 am

    The problem is that both function<int()> and function<int(int)> are constructible from the same function. This is what the constructor declaration of std::function looks like in VS2010:

    template<class _Fx>
    function(_Fx _Func, typename _Not_integral<!_Is_integral<_Fx>::value, int>::_Type = 0);
    

    Ignoring the SFINAE part, it is constructible from pretty much anything.
    std::/boost::function employ a technique called type erasure, to allow arbitary objects/functions to be passed in, so long they satisfy the signature when being called. One drawback from that is, that you get an error in the deepest part of the implementation (where the saved function is being called) when supplying an object which can’t be called like the signature wants it to, instead of in the constructor.


    The problem can be illustrated with this little class:

    template<class Signature>
    class myfunc{
    public:
        template<class Func>
        myfunc(Func a_func){
            // ...
        }
    };
    

    Now, when the compiler searches for valid functions for the overload set, it tries to convert the arguments if no perfect fitting function exists. The conversion can happen through the constructor of the parameter of the function, or through a conversion operator of the argument given to the function. In our case, it’s the former.
    The compiler tries the first overload of a. To make it viable, it needs to make a conversion. To convert a int(*)() to a myfunc<int()>, it tries the constructor of myfunc. Being a template that takes anything, the conversion naturally succeeds.
    Now it tries the same with the second overload. The constructor still being the same and still taking anything given to it, the conversion works too.
    Being left with 2 functions in the overload set, the compiler is a sad panda and doesn’t know what to do, so it simply says the call is ambigious.


    So in the end, the Signature part of the template does belong to the type when making declarations/definitions, but doesn’t when you want to construct an object.


    Edit:
    With all my attention on answering the title-question, I totally forgot about your second question. 🙁

    Can I circumvent it or will I have to keep the (annoying) explicit casts?

    Afaik, you have 3 options.

    • Keep the cast
    • Make a function object of the appropriate type and pass that

      function<int()> fx = x;
      function<int(int)> fy = y;
      a(fx);
      a(fy);

    • Hide the tedious casting in a function and use TMP to get the right signature

    The TMP (template metaprogramming) version is quite verbose and with boilerplate code, but it hides the casting from the client. An example version can be found here, which relies on the get_signature metafunction that is partially specialized on function pointer types (and provides a nice example how pattern matching can work in C++):

    template<class F>
    struct get_signature;
    
    template<class R>
    struct get_signature<R(*)()>{
      typedef R type();
    };
    
    template<class R, class A1>
    struct get_signature<R(*)(A1)>{
      typedef R type(A1);
    };
    

    Of course, this needs to be extended for the number of arguments you want to support, but that is done once and then buried in a "get_signature.h" header. 🙂

    Another option I consider but immediatly discarded was SFINAE, which would introduce even more boilerplate code than the TMP version.

    So, yeah, that are the options that I know of. Hope one of them works for you. 🙂

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

given the following code: import ctypes ip=192.168.1.1 thisdll = ctypes.cdll['aDLL'] thisdll.functionThatExpectsAnIP(ip) how can I
Given the following code, is there a way I can call class A's version
I have the following code, which is supposed to try to parse a given
Given the following code: // range heap example #include <iostream> #include <algorithm> #include <vector>
For some reason the following code fails. You can't simply erase a reverse_iterator by
I have the following bit of code, I expect that given cstdio is included
Given the following code (that doesn't work): while True: # Snip: print out current
Given the following code snippet from inside a method; NSBezierPath * tempPath = [NSBezierPath
Given the following code: var people = new List<person>(){ new person { Name =
Given the following code,the hover function works correctly, but when clicked, loses the clicked_no_event_box

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.