-1

I think I need a template friend function in a normal class. This function will be doing some complicated allocation in shared memory and some other poking around in the hardware and OS. But I have excluded all of that to show the problem is related to the -template- and/or -friend- aspects and not something more sinsiter. The main part is that I need the instance of the class and its member data all be allocated with an allocator that I can pass as a generic parameter.

class Foo    {
public:
    const long * const larry;
    const long * const curly;
    const long * const moe;
private:
    Foo() : larry(0), curly(0), moe(0) {}; // not used

    Foo(long * _larry, long * _curly, long * _moe) :
        : larry(_larry), curly(_curly), moe(_moe)
    {
        // some unrelated memory management and OS stuff happens here
    }

    template<class Alloc> friend const Foo * alloc_Foo(long count);

public: // factories

    template<class Alloc> const Foo * factory_A(long);
//  template<class Alloc> const Foo * factory_B(long);
// ...
//  template<class Alloc> const Foo * factory_G(long);

};

template<class Alloc> const Foo * alloc_Foo(long count)
{
    typename Alloc::template rebind<long>::other a_long;
    // allocate internal parts in shared memory
    const long * const larry = a_long.allocate(count+2);
    const long * const curly = a_long.allocate(count+44);
    const long * const moe   = a_long.allocate(count*3);

    Alloc alloc;
    const Foo * const p_foo = alloc.allocate(1);
    alloc.construct(p_foo, Foo(larry, curly, moe));
);

I think this should be the right solution. Only alloc_Foo should call the constructor and only the factory methods should call alloc_Foo. Instance of Foo and its separately allocated internal parts are created in shared memory where they are supposed to be and all of complicated allocation stuff is hidden in the alloc_Foo friend template. This part I can get to work fine. I don't even mind having the implementation for alloc_Foo in the same file because it is short and simple. But the factories that call alloc_Foo are large and complex and would clutter up an otherwise clean and simple class with tens of includes and many hundreds of lines of code.

I tried to include the implementations at the end so I could have each factory in a separate file.

#include "factory_A.tpp"
#include "factory_B.tpp"
// etc.

Then in the .tpp files I put the actual code but I cannot seem to include anything, say bar.h, there. The #include rules seem to fall apart. I'm afraid that it has something to do with my template allocator friend. I would sure hate to lose that since it solves so many of my other problems.

../blah/blah/factory_A.tpp:10:9: error: 'Bar' was not declared in this scope
make: *** [blah/blah/main.o] Error 1

Normally I wouldn't be so hung up on a scope deal but this is an unusal combination for me. Maybe I'm overthinking the whole deal. I reason that alloc_Foo must be a friend so it can see the constructors I am hiding. I reason that it should also be private and that only the factories should be able to use it. I reason that both the allocator and factories are not actually part of the function. They don't have or need 'this'. Maybe they should be static. I reason that it must be a template because I need to use a special allocator on many internal parts and the actual object itself for each instance. Should it be static.

Can anybody help?

Thanks.

wapadomo
  • 57
  • 1
  • 5
  • 3
    A very hard to read question.. – Karthik T Jan 08 '13 at 01:40
  • What do you mean by "but I cannot seem to include anything, say bar.h, there"? What is stoping u? – Karthik T Jan 08 '13 at 01:42
  • Are you saying that when you use `#include ` in factory_A.tpp, that you get one error, and then when you don't include it, you get the `'Bar' was not declared...` error? Or are you saying that even though you use `#include ` in factory_A.tpp, you still get the `'Bar' was not declared...` error? – Vaughn Cato Jan 08 '13 at 01:54
  • Yes, I cannot #include in the foo.tpp file. And of course when I don't include it it can't be seen. I understand that nothing is really compiled until the point of instantiation. What I don't understand is why the preprocess doesn't work the same way for templates. – wapadomo Jan 09 '13 at 17:20
  • It does work the same. You're doing something wrong, but you haven't given enough information to work out what it is. – Jonathan Wakely Jan 09 '13 at 22:13

1 Answers1

0

I am sure this has nothing to do with templates or friends. The preprocessor knows nothing about templates or friends, it just opens files and inserts their contents into other files, templates and friends cannot possibly "make include rules fall apart". What you're doing should be fine.

Check the include guards on bar.h, are they the same as some other file?

Did you #include "factory_A.tpp" while some namespace scope is open? Try closing the namespace before the extra includes at the bottom of the file.

Or is Bar in some namespace and you should be saying x::Bar?

Are you picking up the wrong bar.h? Try renaming the header file to something else, something distinctive that no other header will be called, and change the #include to that.

If none of those works, reduce the code to a minimal complete example that reproduces the problem. Currently you're not showing enough code to see where the real problem is, but it's almost certainly not what you've suggested and is somewhere else in code you haven't shown.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • I originally thought the same way. But now I read stull like this [link]http://www.cplusplus.com/doc/tutorial/templates at the bottom **bold**Templates and multiple-file projects**bold** – wapadomo Jan 09 '13 at 17:28
  • (1) cplusplus.com is a crap reference (2) it's misleading, there is no problem splitting templates across several headers, as long as all the headers are included in any file that uses the templates. You cannot put template definitions in a separate `.cpp` file from code that uses them. Your problem is not due to using templates and friends. You've just got your headers wrong. – Jonathan Wakely Jan 09 '13 at 22:12
  • Ok. This last comment straightened me out (I think). We use a .tpp extension for our template implementations. The header includes the .tpp and the using class includes the header. In the .tpp file I was also trying to include some stuff that the header didn't need to know about but the .tpp did. Your comment made me check what I had Eclipse set up to do with .tpp files. It was set to .cpp not .h. Thanks. – wapadomo Feb 08 '13 at 01:49