Search code examples
c++visual-c++std-functionvisual-studio-2012

Odd behaviour of std::function copy operator (MSVC2012)


I've run in problem of bad_function_call exception when trying to play with function<> object.

Discovering the problem lead me to next simple sample: http://ideone.com/Mwvw7s

Main excerpts:

std::function<void(void*)> f1;
std::function<void(const void*)> f2;
f1 = f2; // Could fail, but didn't

if(f1)
    f1(nullptr); // Should never run
else 
    std::cout << "Skip f1" << std::endl; // Should run

if(f2)
    f2(nullptr);
else 
    std::cout << "Skip f2" << std::endl;

This the f1 become valid, regardless the f2. This problem occurs only on MSVC2012 (didn't try any other version of MS compiler) and works as expected in GCC.

The questions are:

  1. Is this problem MSVC2012 specific? (Could anyone test on MSVC2013)
  2. Is this problem well-known?
  3. [If 1 and 2 is 'no'] Whom should I complain?

Updates

  1. The MSVC2013 doesn't reproduce such problem.
  2. just in case anyone care, GitHub repository with problem: https://github.com/comargo/functional_test

Solution

  • This would appear to be a problem with MSVC2012; MSVC2013 runs it correctly (live example).

    Assignment of a function class template instantiation instance from a distinct instantiation of the template (i.e. with a different signature) delegates to the constructor, and is handled by a special clause of [func.wrap.func.con]:

    8 - Postconditions: !*this if any of the following hold: [...]

    • F is an instance of the function class template, and !f

    I would guess that the library implementors failed to implement this clause for MSVC2012; when converting between function class template instantiations, the most straightforward strategy is to wrap the source type in a converting wrapper; it would be easy to forget to check that the source instance is engaged.

    As a workaround you could write:

    f2 ? (f1 = f2) : (f1 = nullptr);