Boost logo

Boost :

Subject: Re: [boost] RFC: type erasure
From: Vicente Botet (vicente.botet_at_[hidden])
Date: 2011-05-25 04:34:26


Steven Watanabe-4 wrote:
>
> AMDG
>
> On 05/24/2011 02:07 PM, Vicente Botet wrote:
>>
>> Steven Watanabe-4 wrote:
>>> On 05/23/2011 02:34 PM, Vicente Botet wrote:
>>>>
>>>> I like how concepts are materialized using a template class that
>>>> implements
>>>> the default behavior of the concept and that can be specialized to map
>>>> type
>>>> to concepts. I understand that you need a second step to introduce the
>>>> functions themselves specializing concept_interface.
>>>>
>>>> What I don't understand is the overloading issues. Could you use a
>>>> concrete
>>>> example to try to clarify the problems you have addressed?
>>>>
>>>
>>> Okay. Problem 1: Name hiding for member functions.
>>>
>>> typedef mpl::vector<
>>> callable&lt;int(int)&gt;,
>>> callable&lt;double(double)&gt;
>>>> test_concept;
>>>
>>> If we just use the basic definition of
>>> concept_interface, the second overload
>>> will hide the first since the inheritance
>>> structure looks like:
>>>
>>> struct callable1 {
>>> int operator()(int);
>>> };
>>>
>>> struct callable2 : callable1 {
>>> double operator()(double);
>>> };
>>>
>>
>> I find this normal and expected behavior, so I don't see yet why do you
>> need
>> to avoid this hiding.
>>
>
> It's normal in the sense that it's what C++
> does by default. I don't see how it can possibly
> be the expected behavior that:
>
> struct func {
> template<class T>
> T operator()(T t) { return t; }
> };
>
> typedef mpl::vector<
> callable&lt;int(int)&gt;,
> callable&lt;double(double)&gt;
>> test_concept;
>
> func f1;
> any<test_concept> f(f1);
> f(1); // calls func::operator()<double>??
>
> From the point of view of someone trying to
> use the library, the two instances of callable
> are equal. Having one hide the other is surprising.
>

 I understand it now. It seems that I have forgotten this case on
Boost.Opaque.
Many many thanks.

>>> For free functions, I had a problem akin to name
>>> hiding when I defined a single namespace scope
>>> overload with concept_interface arguments. Using
>>> an inline friend function that takes the derived
>>> type works with some care to avoid duplicate
>>> definitions.
>>>
>>
>> I'm sorry but I don't reach to see what is the real problem. I guess it
>> is
>> because I don't see the need of introducing the using sentence. Please
>> could
>> you present a real concrete case of overloading free functions that needs
>> two different specializations of concept interface?
>>
>
> Consider operator+. Either the first argument
> or the second argument or both may be a
> type_erasure::any. I need two specializations,
> because there are two arguments. To use
> friend function defined inline I have to
> inject operator+ into exactly one of the
> arguments.
>

I don't see if I understood it now. I suspect that you mean that either the
first argument
or the second argument or both may be a placeholder, isn't it?

I originally tried to handle free functions with
namespace scope overloads like this:

...

Unfortunately, this failed with the example
print_sequence.cpp, because of
ostreamable<_os, const char*>, ostreamable<_os, _t>
Only one of these was being considered
for overload resolution.

>>> You can check the tests for details on what I expect
>>> to work. Most of the tests for specific concepts
>>> have a test_overload test case.
>>>
>>>
> I've read some of them. I guess I understand what you expect to work, but
> I
> don't see why you need to specialize twice the concept_interface class for
> the same concept.

I couldn't get all the tests to pass with any other
solution I tried. If you have a simpler way to
specialize concept_interface for ostreamable or
callable that passes all my tests I'd love to
hear about it, but I've tried and this is the
best I could come up with.

I'm just trying to understand what kind of problems you have addressed to
see if I can have the same in Boost.Opaque.

To summarize the reasons for multiple specializations:
- For member functions, the second and subsequent instances
  of a concept need to be treated differently from
  the first, because they need an extra using declaration
  (which would be ill-formed in the first occurrence).
- For non-member functions, one specialization is needed
  for each argument that can be a type_erasure::any to
  make sure that the function gets added to the overload
  set regardless of what subset of the arguments is erased.

Thanks again for the clearer explanations.

Best,
Vicente

--
View this message in context: http://boost.2283326.n4.nabble.com/RFC-type-erasure-tp3542886p3549166.html
Sent from the Boost - Dev mailing list archive at Nabble.com.

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