C++ - Static templated method inside a class
-
So, I finally decided to dive into C++ world, trying to adapt some C# code I've been working on lately. So here's what I have. bin.h file:
#pragma once
namespace Maths {
class Bin
{
public:
template static const T GetMask(int);
};}
bin.cpp file:
#include "bin.h"
namespace Maths {
template const T Bin::GetMask(int count) {
return (T)0; // Fake implementation
}}
This compiles just fine. However, in the same console project, when I write:
#include "bin.h"
using namespace Maths;
int main() {
unsigned char value = Bin::GetMask<unsigned char>(0);
}I get a nasty LNK2019 linkage error on compilation:
Error LNK2019 unresolved external symbol "public: static unsigned char const __cdecl Maths::Bin::GetMask(int)" (??$GetMask@E@Bin@Maths@@SA?BEH@Z) referenced in function "int __cdecl main(void)" (?main@@YAXXZ)
In the
Bin
class, I have a couple of other (non-generic) methods, which I can use just fine. I suspect a problem with static templated methods specifically, but I can't understand the core problem. Maybe I just try to do something which is not possible (using a static generic method), but I cannot figure out why it would not be possible. Anyone could give me a hint on this?"I'm neither for nor against, on the contrary." John Middle
-
So, I finally decided to dive into C++ world, trying to adapt some C# code I've been working on lately. So here's what I have. bin.h file:
#pragma once
namespace Maths {
class Bin
{
public:
template static const T GetMask(int);
};}
bin.cpp file:
#include "bin.h"
namespace Maths {
template const T Bin::GetMask(int count) {
return (T)0; // Fake implementation
}}
This compiles just fine. However, in the same console project, when I write:
#include "bin.h"
using namespace Maths;
int main() {
unsigned char value = Bin::GetMask<unsigned char>(0);
}I get a nasty LNK2019 linkage error on compilation:
Error LNK2019 unresolved external symbol "public: static unsigned char const __cdecl Maths::Bin::GetMask(int)" (??$GetMask@E@Bin@Maths@@SA?BEH@Z) referenced in function "int __cdecl main(void)" (?main@@YAXXZ)
In the
Bin
class, I have a couple of other (non-generic) methods, which I can use just fine. I suspect a problem with static templated methods specifically, but I can't understand the core problem. Maybe I just try to do something which is not possible (using a static generic method), but I cannot figure out why it would not be possible. Anyone could give me a hint on this?"I'm neither for nor against, on the contrary." John Middle
-
The
Maths
namespace does not contain a definition/declaration ofBin::GetMask(int);
only one ofBin::GetMask(int);
. Just remove the<unsigned char>
piece and it should be fine.Thank you Richard for answering. However, if I try to remove the
<unsigned char>
piece (namely:unsigned char value = Bin::GetMask(0);
), the editor itself complains about the fact that no instance of function template "Maths::Bin::GetMask" matches the argument list. Moreover, theBin::GetMask(int)
is actually declared inMaths
namespace. Problem seems to be with the .cpp part: the editor/IDE can see the definition of the generic method (since the editor does not complain when I try to use it, and the object explorer clearly displays the method with correct signature), but, on compilation, the linker cannot make a link to the actual implementation. How can I correctly declare a static, generic method inside a non-generic class, then? Thanks for your time :)"I'm neither for nor against, on the contrary." John Middle
-
The
Maths
namespace does not contain a definition/declaration ofBin::GetMask(int);
only one ofBin::GetMask(int);
. Just remove the<unsigned char>
piece and it should be fine.Anyway, I found the issue. I cannot implement a template method in the .cpp file, like I did with other non generic methods. I moved the implementation of the generic method in the .h header file, and now everything is ok. I guess I have to dig deeper in the translation unit concept :)
"I'm neither for nor against, on the contrary." John Middle
-
Anyway, I found the issue. I cannot implement a template method in the .cpp file, like I did with other non generic methods. I moved the implementation of the generic method in the .h header file, and now everything is ok. I guess I have to dig deeper in the translation unit concept :)
"I'm neither for nor against, on the contrary." John Middle
-
Thank you Richard for answering. However, if I try to remove the
<unsigned char>
piece (namely:unsigned char value = Bin::GetMask(0);
), the editor itself complains about the fact that no instance of function template "Maths::Bin::GetMask" matches the argument list. Moreover, theBin::GetMask(int)
is actually declared inMaths
namespace. Problem seems to be with the .cpp part: the editor/IDE can see the definition of the generic method (since the editor does not complain when I try to use it, and the object explorer clearly displays the method with correct signature), but, on compilation, the linker cannot make a link to the actual implementation. How can I correctly declare a static, generic method inside a non-generic class, then? Thanks for your time :)"I'm neither for nor against, on the contrary." John Middle
-
Anyway, I found the issue. I cannot implement a template method in the .cpp file, like I did with other non generic methods. I moved the implementation of the generic method in the .h header file, and now everything is ok. I guess I have to dig deeper in the translation unit concept :)
"I'm neither for nor against, on the contrary." John Middle
phil.o wrote:
the translation unit concept
The only reason for creating header files is when you have a set of common definitions that need to be shared by multiple translation units. If you only have a single .cpp file then all the definitions can safely be put in there. The
#include
statement is recognised by the preprocessor which reads all the include files and creates a new text file containing all the included code followed by the user written C/C++ code, and passes that new composite to the actual compiler. -
phil.o wrote:
the translation unit concept
The only reason for creating header files is when you have a set of common definitions that need to be shared by multiple translation units. If you only have a single .cpp file then all the definitions can safely be put in there. The
#include
statement is recognised by the preprocessor which reads all the include files and creates a new text file containing all the included code followed by the user written C/C++ code, and passes that new composite to the actual compiler.I have learnt it the hard way :) This explains why everything was fine as far as the editor/IDE were concerned, and why the issue only occurred on the linking phase. That's quite confusing for a beginner.
"I'm neither for nor against, on the contrary." John Middle
-
I have learnt it the hard way :) This explains why everything was fine as far as the editor/IDE were concerned, and why the issue only occurred on the linking phase. That's quite confusing for a beginner.
"I'm neither for nor against, on the contrary." John Middle