4

I have and header with a template class, which has only static functions and fields.

template<typename T> class Luaproxy {

    static std::map<std::string, fieldproxy> fields;
    static const char * const CLASS_NAME;
    static void addfields();
    static int __newindex(lua_State * l){
        //implemented stuff, references to fields...
    }
    //etc
}

As you can see some of the functions are only declared, because I intend to implement them with template specialization.

In a .ccp file I have:

struct test { int a; }
template<> map<string, fieldproxy> Luaproxy<test>::fields;
template<> const char * const Luaproxy<test>::CLASS_NAME=typeid(test).name();
template<> void Luaproxy<test>::addfields(){
    //stuff, references to fields...
}

I get undefined reference errors to Luaproxy<test>::fields from both functions that are implemented in the header and those that are only specialized in the .cpp. Note that Luaproxy<test>::CLASS_NAME and Luaproxy<test>::addfields seem to be found in linking.

What makes that map so special?

AusCBloke
  • 18,014
  • 6
  • 40
  • 44
Lorenzo Pistone
  • 5,028
  • 3
  • 34
  • 65
  • Make "template class Luaproxy<>;" entry at the top of your cpp file. I think that must solve it – Arunmu Dec 25 '11 at 05:26

2 Answers2

5

I finally managed to get it working, but I couldn't really say why my compiler (gcc 4.6.1) needs it this way: template<> std::map<std::string, fieldproxy> Luaproxy<test>::fields=std::map<std::string, fieldproxy>();

The explicit constructor seem to convince gcc to effectively emit the variable. I asked #gcc for clarification, but unfortunately that channel is always silent.

Lorenzo Pistone
  • 5,028
  • 3
  • 34
  • 65
2

I built your code with just several extra semicolons and namespace tags in VC9, but there was neither compile error nor link error.

here are what I built:

Luaproxy.h file:

#pragma once
#include <map>
#include <string>
typedef int fieldproxy;
struct lua_State;
struct test {
    int a;
};
template<typename T>
class Luaproxy
{
public:
    static std::map<std::string, fieldproxy> fields;
    static const char * const CLASS_NAME;
    static void addfields();
    static int __newindex(lua_State * l){}
};

Luaproxy.cpp file:

#include "Luaproxy.h"
template<> std::map<std::string, fieldproxy> Luaproxy<test>::fields;
template<> const char * const Luaproxy<test>::CLASS_NAME=typeid(test).name();
template<> void Luaproxy<test>::addfields(){}

main.cpp file:

#include "Luaproxy.h"
int _tmain(int argc, _TCHAR* argv[])
{
    Luaproxy<test> *p = new Luaproxy<test>;
    p->fields["foo"] = 0;
    delete p;
    return 0;
}
legendlee
  • 568
  • 4
  • 12
  • your code doesn't work for me, which is weird. My compiler is gcc 4.6.1. By chance, I added an explicit constructor declaration to fields, and now it compiles. In 3 hours I will be able to self-reply and explain this more deeply. – Lorenzo Pistone Dec 25 '11 at 09:35