简体   繁体   中英

Is template type of a std::function detached by std::bind an undefined behavior?

i am working on MSVC

static bool filter_entity(void* entity)
{
    return entity == nullptr;
};
template<typename F>
static bool Dispatch(const F& filter)
{
    return filter(nullptr);
};
int main()
{
    void* ptr = new int();
    if (Dispatch(std::bind(&filter_entity, ptr))) cout << "nullptr" << endl;
    else cout << "intptr" << endl;
    //ret: intptr
}

it is weird that invoking a function with the const nullptr argument actually insert the ptr as argument, i wonder if it is an undefined behaviour.

Also is there a way to call filter() for this instance and make the template and std::bind significant for multiple situations?

From cppreference.com :

If some of the arguments that are supplied in the call to [the bound object] are not matched by any placeholders stored in [the bound object], the unused arguments are evaluated and discarded.

The bound object from the question has no placeholders. So the nullptr in

return filter(nullptr);

is evaluated and discarded, and the result is the same as if

return filter();

was called. If we interpret the binding, this is the same as

return filter_entity(ptr);

(or would be if ptr was in scope). If you want to use the nullptr in the return statement, you would need to use std::placeholders::_1 in your std::bind .


A followup question to this might be Why do objects returned from bind ignore extra arguments?

Stop using std::bind . std::bind is not worth becoming an expert in. Become an expert in lambdas instead.

std::bind was imported from boost::bind in at the same time lambdas arrived. It was a library solution that lambdas solved many of the same problems as it did. In std::bind could do a few things lambdas could not; since then lambda became more poeerful, and this is no longer true.

std::bind is full of strange corners. You are witnessing one of them; honestly one of the more pedestrian ones.


std::bind does not return a std::function . std::bind returns an unnamed object with an operator() . When you call the operator() on it, it first grabs its bound arguments (eith some unwrapping of references), does some rerouting based on placeholders and bound subexpressions,.

After a complex step there, it then "silently" discards extra arguments.

So you bound the first argument to nullptr; the later non null is evsluated and discarded.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM