0

My code contains two parts - a class template test inside namespace my, and a function frobnicate in a global namespace. The class template wants to use this function in one of its methods, and I want to declare it near its use:

namespace my
{
    template <class T>
    struct test
    {
        void do_stuff(T& i)
        {
            void frobnicate(T&);
            frobnicate(i);

            // more code here
        }
    };
}

struct SomeClass {};

void frobnicate(SomeClass& i)
{
    // some code here
}

int main()
{
    my::test<SomeClass> t;
    SomeClass object;
    t.do_stuff(object);
}

This works in MS Visual Studio 2017 due to a bug (described here), because Visual Studio declares the function in the global namespace, while according to the Standard, such declaration declares the function in current namespace.

However, gcc rightfully complains:

... undefined reference to `my::frobnicate(SomeClass&)'

Can I make it work in gcc or any other standard-compliant compiler?


If I put the declaration of frobnicate before declaring template test, the code works. However, in my real code, these two parts of code are in unrelated header-files, and I want my code to work regardless of the order of #includes, if possible.

anatolyg
  • 26,506
  • 9
  • 60
  • 134
  • The solution seems rather obvious: put the declaration of `frobnicate()` in a third header file, with `ifndef/define` guards, and include this header file at the beginning of your two existing header files, before they open a namespace declaration. Not sure why exactly this seemingly straightforward, and typical solution won't work for you. – Sam Varshavchik Feb 17 '19 at 17:08
  • It will surely work, as a last resort. My problem with this solution is, it makes the header-file which defines the template dependent on an unrelated header-file which defines `SomeClass`. This dependency doesn't make sense in my code, especially if I have several `SomeClass`es for which the template should work. – anatolyg Feb 17 '19 at 17:12
  • 1
    That's what "forward declarations" are for. The new header file ***does not*** require that other, entire header to be included. It only needs to contain "`class SomeClass; void frobnicate(SomeClass &);`". End of story. – Sam Varshavchik Feb 17 '19 at 17:17

2 Answers2

2

Just forward declare your frobnicate function as a template before the namespace.

template <class T>
void frobnicate(T&);

namespace my {

template <class T>
struct test
{
    void do_stuff(T& i)
    {
        frobnicate(i);
        // more code here
    }
};
}  // close my namespace
Bo R
  • 2,334
  • 1
  • 9
  • 17
0

I think you could simply declare frobnicate in seperate file and include it before creating namespace my.Or you could declare the function as a macro with #define in the same file. Then you can call frobnicate in the do_stuff in my.

Otherwise you can't call an undefined function.

SSG
  • 100
  • 7