Boost logo

Boost :

Subject: Re: [boost] [type_traits][function_types] Discard param const qualification, bug or feature?
From: Rob Stewart (robertstewart_at_[hidden])
Date: 2013-10-01 06:22:10


On Sep 30, 2013, at 9:46 PM, Mostafa <mostafa_working_away_at_[hidden]> wrote:

> On Mon, 30 Sep 2013 14:20:40 -0700, Jonathan Wakely <jwakely.boost_at_[hidden]> wrote:
>
>> On 30 September 2013 21:53, Mostafa wrote:
>>>>
>>>> Why do you choose a different "efficient type" for an 'int' parameter vs a 'const int' parameter?
>>>
>>> You're most likely reading this message out of context. If you start with Sergey's response it'll probably make more sense.
>>
>> No, I've read the whole thread.
>>
>> It sounds like your code to generate signatures has a bug and doesn't model the rules of C++.
>>
>> I repeat: Why would you choose a different "efficient type" for an 'int' parameter vs a 'const int' parameter?

Let me rephrase that. int and int const are passed from the caller to the function by value. What the function does with the parameters is immaterial to the caller, so why would you treat them differently when forwarding them?

>> I would say if you're doing that then you're doing something wrong, so should fix it to remove top-level const, because that's what C++ does
>> and because it's probably the right thing to do anyway.
>
> Ah, ok, I had the use case reversed. Let's try this:
>
> struct SomeUserClass
> {
> static void foo(int const x)
> {
> SomeCodeGenClass::foo(x);
> }
> };
>
> SomeCodeGenClass::foo is a mere parameter forwarder, so the goal is to do it as efficiently as possible. It's signature is constructed from SomeUserClass::foo. For correctness, that should be:
>
> void SomeCodeGenClass::foo(int const & x)

No, that should be int x. The reference is a pessimization for int. For larger types, const & is appropriate, though it will apply regardless of the top-level constness of the parameter. IOW, if the type is cheap to copy, copy it, regardless of top-level constness. If it isn't, pass it by const &. That's what call_traits<T>::param_type does for you.

> But, function_types<SomeUserClass::foo>::arg1_type resolves to int, so that add_reference'ing will give the following signature for the TMP constructed SomeCodeGenClass::foo
>
> void SomeCodeGenClass::foo(int & x)
>
> Which will give a compiler error for SomeUserClass::foo. Note, this is a really watered down example, so if function_types doesn't work with static member functions make the functions free, etc...
>
> And I'm not arguing that either type_traits or function_types should behave differently, I was wondering if a general solution exists for such a situation.

In the end, IIUC, you want a wrapper that determines the optimal argument forwarding scheme such that a user can wrap their function and then call the wrapper, as though it was their function, and get optimal argument forwarding. Is that right?

Are you restricted to C++03 or is C++11 available? In either case, if I understand your goal, you're talking about perfect forwarding. It's the implementation that will differ.

___
Rob

(Sent from my portable computation engine)


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk