0
101 Jun 23, 2011 at 21:20

Hello everyone,

Long time no write, been busy with my master thesis project for the past few months :)

However, in the final coding stage, I stumbled upon a small problem I can’t seem to solve: I get an unresolved external symbol when compiling a class that has a private member function template with the function definition in the .cpp file.

I already know that templates can’t be exported and should be placed in the header (!!), but this case is different: The corresponding function is inlined and only used in the corresponding .cpp file.

In particular,

// file.h
class SomeClass
{
template <typename A, typename B>
__forceinline shared_pointer<A> doSomething
(B& b, weak_pointer<T> a);
};

// file.cpp
template <typename A, typename B>
__forceinline shared_pointer<A> SomeClass::doSomething
(B &b, weak_pointer<T> a)
{
// ...
}

shared_pointer<BaseOfA> SomeClass::callMethod()
{
return doSomething(myb, mya); // only use of doSomething here
}


Up to now, I was of the opinion that this is possible in standard C++.
However, I get a linker error (unresolved external symbol) once I include the appropriate .cpp file into compilation. I guess this is a bug (VS2010 SP1) or some cross-influence from another code problem.

Placing the function definition into the header works, but the function is quite intricate, and I’d rather keep it hidden from potential header users.

Up to now, I haven’t been able to google up anything relevant…
Ideas / suggestions / known bugs / or should this generally not work ?

Thank you for your time! :)
Cheers,
- Wernaeh

#### 9 Replies

0
167 Jun 23, 2011 at 21:31

That seems odd to me; I too would have expected this to work correctly. Anyway, if the function is used only as a helper in the implementation of SomeClass, perhaps it does not need to be in SomeClass at all, but could be a free function (perhaps a friend, if it needs to get at private members)?

0
101 Jun 23, 2011 at 23:16

Okay, the free function workaround did the trick, had it as friend and passed in the original this-pointer as parameter. Thank you, Reedbeta ! :)

The original problem still is weird though, if I construct a similar case in another file it compiles without problems… Anyways, still too much to round up in my thesis to investigate in depth right now :o)

Cheers,
- Wernaeh

0
101 Jun 24, 2011 at 00:00

Be careful with __forceinline, it could lead to less optimal code. The compiler usually has the better judgement on what to inline and what not.

0
101 Jun 24, 2011 at 01:31

Yup, I don’t normally use __forceinline - in this case, I just tried to give the compiler a broad hint that my function is never used outside the implementation file, sadly without success ;) Thank you for your input, though!

0
102 Jun 24, 2011 at 03:37

Do you guys really use templates for everything? Sorry for being the “against”, but I’m not a big fan of templates at all. I do like metaprogramming though, just not too much in templates form. So I avoid them as much as possible.

Ok .oisyn, you can call me stupid now. ;)

0
167 Jun 24, 2011 at 03:53

I don’t use them for “everything”, but I use them at times when appropriate - mostly for collections, and generating vector/matrix classes of different dimensions.

I did make one foray into sophisticated template metaprogramming with my luabridge library, but after that I decided I had enough. B) I prefer the D approach to metaprogramming. It has templates, but allows syntax that looks much more like regular C-syntax than a whole other language. It also has a few things like mixins and tuples that are more powerful than what C++ offers. One guy wrote a compile-time raytracer…now that’s crazy! ;)

0
101 Jun 24, 2011 at 09:10

I rarely use templates in production code, other than the obvious cases such as collections, smart pointers and the occasional duck typing.

But I definitely like to play with them in test code ;)

0
101 Jun 24, 2011 at 15:00

Mainly, I use templates when I have a code path that should be the same for several (unrelated, no common base class) types.

For instance, consider a ResourceCache class that holds lots of different resource types. Internally, it houses a unique map (name to weak pointer) for each resource type. If a resource is not found or the weak pointer is empty, the resource should be created and loaded from file. Otherwise, the weak pointer is locked to a shared pointer and returned.

Now, one could write a single request function for each resource type, which means around 20 lines per resource type and lots of copy and paste.

Alternatively one could write a request function template that accepts as template parameters the type of resource to create, and the lookup map for the resource type. To keep the interface simple for clients (template free and exportable), this function template is wrapped into resource-specific request calls, which totals at around 4 lines per resource type.

0
101 Jun 24, 2011 at 15:54

I think you can resolve this linker error, by putting something like this in the end of file.cpp

template shared_pointer<MyA> SomeClass::doSomething<MyA, MyB>(MyB &b, weak_pointer<MyA> a);


Where MyA and MyB are the types you intend to use with doSomething.