Enlico
Enlico

Reputation: 28520

Is the inconsistency between conversions allowed by std::not_fn and std::function constructor intended?

If you have something like this,

struct Foo {
};

constexpr auto pred = [](){
    return Foo{};
};

calling std::not_fn(pred) will fail to compile, expectedly.

However, adding an explicit conversion operator from Foo to bool,

struct Foo {
    explicit operator bool() {
        return true;
    }
};

is enough to make std::not_fn(pred) compile.

This at first seemed reasonable to me. But then I realiazed that:

    std::function<bool(int)> f{std::not_fn(pred)}; // compiles
    std::function<bool(int)> g{pred};              // fails to compile

I do see some reason for the permissiveness of std::not_fn: based on its name, it is supposed to negate a predicate, so fair enough if it tries to convert the return type of the given function to bool.

But why shouldn't std::function adopt a similar policy? After all, given a function of type ConvertibleToFoo(Bar), what would be wrong in constructing a std::function<Foo(ConvertibleToBar)>?

Or, if std::function doesn't allow that, why does std::not_fn allow it?

Indeed, it seems to me that the fact that std::not_fn is able to act on functions that return a non-bool-but-explicitly-convertible-to-bool type is a happy (or not happy) side effect of the fact that it uses !, in its implementation, in front of the return type of the provided function.


Interesting blog post from Arthur O’Dwyer regarding covariance and contravariance.

Upvotes: 5

Views: 94

Answers (0)

Related Questions