Boost logo

Boost :

From: Marco Costalba (mcostalba_at_[hidden])
Date: 2008-03-20 21:26:59


On Thu, Mar 20, 2008 at 6:19 PM, Mathias Gaunard
<mathias.gaunard_at_[hidden]> wrote:
> Marco Costalba wrote:
> > I have upload in Vault an updated version of the multi-signature
> > function wrapper aka "overload"
> >
> > File is called overload_20_3_2008.zip
>
> I couldn't find any documentation, so I would like to ask you a few
> questions:
>
> The function object can be empty or contain more or less function
> objects. What happens when calling the function object and there is
> nothing corresponding to the given signature?
>

In this case a dereferencing of a NULL pointer occurs with obvious consequences.

I have added the helper is_set to let the user check for it:

void foo(int);

overload<void(int)> f;

cout << f.is_set<void(int)>() << endl; // prints 0

// f(); segfault here !

f.set(foo1);

cout << f.is_set<void(int)>() << endl; // prints 1

f(7); // ok, calls foo1

Other options that I have evaluated are:

- Assert instead of NULL dereferencing: does not gain much at
run-time, always a crash occurs

- Silently fail, as example returning a default value: much more
dangerous then segfaulting IMHO

Any suggestion? (compile time assert does not seem an option because
it's related to the runtime value stored in an auto_ptr pointer).

> I suppose that combination of types that would generate ambiguous
> deduction are detected and generate an error at the declaration of an
> overload?
>

Overload does NOT impose any additional constrain above what C++
states for overloaded member functions:

struct base
{
  void foo1(int) { cout << "base called\n"; }

  void foo2(double) { cout << "double called\n"; }
};

struct derived : base
{
  using base::foo1;
  using base::foo2;

  void foo1(int) { cout << "derived called\n"; }

  void foo2(float) { cout << "float called\n"; }

};

int main(int, char**)
{
    derived d;
    d.foo1(7); // prints "derived called"

    // d.foo2(7); compile error: ambiguous call
}

So, as example:

void foo(int) { cout << "foo called"; }

overload<void(int), void(int)> f(foo); // will work, first signature
is hidden by second one

f(7); // will print "foo called"

IOW the first signature will be hidden by the second one both at
assign time then at calling time, it's like first signature is never
take in account.

Different is the case of ambiguous call...

void test1(float) {}
void test2(double) {}

overload<void(float), void(double)> g(test1, test2);

// g(7); compile error: ambiguous call

So to answer your questions:

- If a signature is declared more then once only the last one is
actually used, the others are hidden (100% harmless)

- If two different signatures are declared then declaration of
overload succeed, but if overload is then called with an argument for
which no exact match occurs, but that can be converted to BOTH the
overloaded function then a compile error occurs of the type "ambiguous
call"

Marco


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