NBcode
NBcode

Reputation: 159

C++: Templates not working from another class

When the following project is compiled, I get the following compiler error: (Visual Studio 2010)

1>usingclass.obj : error LNK2019: unresolved external symbol "public: static int __cdecl c1::arrSize(int * const)" (??$arrSize@H@c1@@SAHQAH@Z) referenced in function "public: void __thiscall usingclass::a(void)" (?a@usingclass@@QAEXXZ)

Code:

Headers:

c1.h

#pragma once
#include <array>
class c1
{
    c1(void);
    ~c1(void);
public:
    template<class T>
    static int arrSize(T arr[]);
};

usingclass.h

#pragma once
#include "c1.h"

class usingclass
{
public:
    usingclass(void);
    ~usingclass(void);
    void a();
};

Source files:

c1.cpp

#include "c1.h"

c1::c1(void)
{
}


c1::~c1(void)
{
}

template <class T>
int c1::arrSize(T arr[])
{
    return (sizeof(arr)/sizeof(arr[0]));
}

usingclass.cpp

#include "usingclass.h"

usingclass::usingclass(void)
{
}


usingclass::~usingclass(void)
{
}

void usingclass::a()
{
    int a[2] = {1,2};
    int b = c1::arrSize<int>(a);
}

How do I fix that?

Upvotes: 1

Views: 203

Answers (3)

Vaughn Cato
Vaughn Cato

Reputation: 64308

Don't do this! The declaration is misleading.

template <class T>
int c1::arrSize(T arr[])
{
    return (sizeof(arr)/sizeof(arr[0]));
}

is equivalent to

template <class T>
int c1::arrSize(T *arr)
{
    return (sizeof(arr)/sizeof(arr[0]));
}

which will not give you want you want. The proper way to do it is like this:

class c1
{
    c1(void);
    ~c1(void);
public:
    template<class T,int N>
    static int arrSize(T (&arr)[N]) { return N; }
};

arrSize takes a reference to an array as a parameter. The type of the array and the size of the array are template parameters and can be deduced by the compiler. The inline member function then just returns the size determined by the compiler.

Upvotes: 7

Apoorva sahay
Apoorva sahay

Reputation: 1930

I think you have to define your template in c1.h itself. Because when you are including c1.h in your usingclass.h, and try to use template it does not find the expansion for template.

Or If you want to go with implementation of template in c1.cpp, then you have to include c1.cpp as well in usingclass.h.

Upvotes: 0

Luchian Grigore
Luchian Grigore

Reputation: 258618

You need to move

template <class T>
int c1::arrSize(T arr[])
{
    return (sizeof(arr)/sizeof(arr[0]));
}

inside c1.h.

Template implementations must be visible to all translation units using that template (unless it's specialized, and in your case it's not).

This solves the compiler error but the underlying issue is solved with Vaughn Cato's answer. I missed that. You'll still need the definition in the header.

Upvotes: 2

Related Questions