TPJ
TPJ

Reputation: 179

Calling a C++ namespace-qualified function within a template function in another namespace

If I have a default function 'foo' defined in a namespace in one header file:

//DefaultFoo.h
namespace DefaultFooNamespace
{
    template <typename T>
    void foo(T& x){/*...*/}
}

and overloads of foo defined in another namespace in one or more other header files, e.g., FooOverloads.h:

//FooOverloads.h
namespace FooOverloadsNamespace
{
    template <typename T>
    void foo(std::vector<T>& x){/*...*/}

    void foo(std::string& x){/*...*/}

    //etc.
}

and I have another function 'bar' which calls foo after bringing both DefaultFooNamespace and FooOverloadsNamespace namespaces into scope (note that I #include only DefaultFoo.h in Bar.h, as DefaultFoo.h contains a single function in a namespace which is intended never to be extended, unlike FooOverloadsNamespace which will be extended by the addition of additional overloads):

//Bar.h
#include "DefaultFoo.h" 

namespace BarNamespace
{
    template <typename T>
    void bar(T& x)
    {
        //... do stuff then call foo
        using DefaultFooNamespace::foo;
        using FooOverloadsNamespace::foo;
        foo(x);
    }
}

'bar' won't compile unless I either make sure FooOverloads.h is #include'd before a #include of Bar.h, or I make sure that FooOverloads.h is #include'd in Bar.h, or alternatively I provide a declaration of a 'foo' function for a dummy class in FooNamespace and #include that in Bar.h, e.g.

//Dummy.h:
struct DummyClass
{
private:
    DummyClass(){}
};
namespace FooNamespace
{
    inline void foo(DummyClass& x);  //purely to open up namespace
}

//Bar.h
#include "Dummy.h"

Is there any way around this, such that I can define bar and avoid having to create redundant code to open up FooNamespace in Bar?

Upvotes: 0

Views: 2083

Answers (1)

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

My solution would be to get rid of the useless DefaultFooNamespace namespace. Put the default foo in the same namespace as the overloads, then bar just does:

using FooNamespace::foo;
foo(x);

The default foo is used if the caller hasn't included a definition of a more appropriate one for the type of x

I don't see a reason for the default foo to be in a separate namespace, especially because doing that requires a separate dummy definition to make bar valid code, when the same overload could serve both purposes.

Upvotes: 0

Related Questions