Search code examples
c++boostoverloadingdeprecatedboost-optional

Overload ambiguity with boost::optional, workaround?


I would like to overload with boost::optional but cannot due to overload ambiguity and am looking for a workaround.

For example, the following code will not compile due to ambiguity:

void foo() { ... }
void foo(const Class& A) { ... }
// \deprecated
void foo(boost::optional<const Class&> A) { A ? foo(A) : foo() }

The reason I want to do this strange thing is because, due to bugs that have arisen from rvalue/lvalue issues with boost::optional, I am replacing boost::optional instances with function overloads instead. The problem is that some API breakages occur so I need to leave the old function definitions deprecated.

An example of API breakages is with other default parameters,

void foo(int a=0, boost::optional<Bar> A=boost::none, float b=0.0) { ... }

requires me to switch the order of arguments:

void foo(int a=0, float b=0.0) { ... }
void foo(Bar A, int a=0, float b=0.0) { ... }

but now the case that breaks is foo(1, boost::none, 3.14); so I want to keep a deprecated function definition just for this type of function call. Is there an elegant workaround?

I suppose one (ugly) possibility is

// \deprecated
void foo(int a, boost::optional<DummyClass> A, float b=0.0) { ... }

but this does not spark joy. Any ideas?


Solution

  • As state in comment, your regular case has typo which does recursive call. Fixed version:

    void foo() { /*...*/ }
    void foo(const Class& A) { /*...*/ }
    
    [[deprecated]] void foo(boost::optional<const Class&> A) { A ? foo(*A) : foo(); }
    

    I am replacing boost::optional instances with function overloads instead.

    So you might replace:

    void foo(int a=0, boost::optional<Bar> A=boost::none, float b=0.0) { /*...*/ }
    

    By

    void foo(int a = 0) {/*..*/}
    void foo(int a, Bar, float b = 0.0f) { /*..*/ }
    void foo(int a, boost::none_t, float b = 0.0f) { /*..*/ }
    
    [[deprecated]] void foo(int a, boost::optional<Bar>, float b = 0.0f);