lundi 20 mai 2019

When to use perfect forwarding and when to be explicit?

Missing the ternary comparison operators in Python (e.g., a <= b <= c), I decided to create a utility for my project

    template <typename T>
    bool between(T&& low, T&& test, T&& high)
    { return ( low <= test && test <= high ); }

I state at the outset that I clearly don't grok perfect forwarding, but I thought this was a tailor-made use for it.

This fails when mixing lvalues and rvalues:

    int const low = 0;
    int const high = 10;

    int test = 42;

    between(low, test, high);

This gives a compile error:

    error: no matching function for call to ‘between(const int&, int&, const int&)’
    note: candidate: template<class T> bool between(T&&, T&&, T&&)
     between(T&& low, T&& test, T&& high)
     ^~~~~~~
    note:   template argument deduction/substitution failed:
    note:   deduced conflicting types for parameter ‘T’ (‘const int&’ and ‘int&’)

I thought the point of perfect forwarding was to be insensitive to constness in templates. Clearly, I was wrong, and this is not a candidate for perfect forwarding, but I would like to understand why.

(lest you get distracted trying to fix my compilation error, I changed the function signature to assume boolean operations are logically const:

    template <typename T>
    bool between(T const& low, T const& test, T const& high);

and the compilation errors go away. I could also pass by value and get the same effect)

Aucun commentaire:

Enregistrer un commentaire