Is it possible to take a parameter by const reference, while banning conversions so that temporaries aren't passed instead?

后端 未结 6 1517
面向向阳花
面向向阳花 2021-01-18 21:58

Sometimes we like to take a large parameter by reference, and also to make the reference const if possible to advertize that it is an input parameter. But by making the refe

6条回答
  •  长情又很酷
    2021-01-18 22:22

    (Answering my own question thanks to this great answer on another question I asked. Thanks @hvd.)

    In short, marking a function parameter as volatile means that it cannot be bound to an rvalue. (Can anybody nail down a standard quote for that? Temporaries can be bound to const&, but not to const volatile & apparently. This is what I get on g++-4.6.1. (Extra: see this extended comment stream for some gory details that are way over my head :-) ))

    void foo( const volatile Input & input, Output & output) {
    }
    
    foo(input, output); // compiles. good
    foo(get_input_as_value(), output); // compile failure, as desired.
    

    But, you don't actually want the parameters to be volatile. So I've written a small wrapper to const_cast the volatile away. So the signature of foo becomes this instead:

    void foo( const_lvalue input, Output & output) {
    }
    

    where the wrapper is:

    template
    struct const_lvalue {
        const T * t;
        const_lvalue(const volatile T & t_) : t(const_cast(&t_)) {}
        const T* operator-> () const { return t; }
    };
    

    This can be created from an lvalue only

    Any downsides? It might mean that I accidentally misuse an object that is truly volatile, but then again I've never used volatile before in my life. So this is the right solution for me, I think.

    I hope to get in the habit of doing this with all suitable parameters by default.

    Demo on ideone

提交回复
热议问题