0

I have a specific question that I can't really find an answer to in all the questions regarding template member functions. I want to write a function that gets me some data and return it as a vector of a specific type.

I have the following:

#include <vector>

class testClass
{
public:
    template <typename T> std::vector<T> getData(int column);
};


template <typename T> std::vector<T> testClass::getData(int column){
    std::vector<T> returnData;
    return returnData;
}

and to call the function:

int main()
{   
    testClass t;
    std::vector<int> data = t.getData(0);
    return 0;
}

When compiling this I get the error:

../templateTest/main.cpp:9:31: error: no matching member function for call to 'getData'
    std::vector<int> data = t.getData(0);
                            ~~^~~~~~~
../templateTest/testclass.h:8:42: note: candidate template ignored: couldn't infer template argument 'T'
    template <typename T> std::vector<T> getData(int column);
                                         ^

Ok, so it can't get the template argument from the template in the return type. To fix this I try to include the template argument in the call:

int main()
{   
    testClass t;
    std::vector<int> data = t.getData<int>(0);
    return 0;
}

This compiles but gives me a linker error:

Undefined symbols for architecture x86_64:
  "std::__1::vector<int, std::__1::allocator<int> > testClass::getData<int>(int)", referenced from:
      _main in main.o

One final try is to include the template argument also in the function definition:

class testClass
{
public:
    template <typename T> std::vector<T> getData<T>(int column);
};

This however doesn't compile... :

../templateTest/testclass.h:8:42: error: member 'getData' declared as a template
    template <typename T> std::vector<T> getData<T>(int column);

Is it possible what I try to do?

Thanks!!

----------EDIT---------

Putting the implementation in the header does work. If you however prefer to have your implementation in the .cpp. Add the the last line for each implementation that you plan on using.

#include "testclass.h"

template <typename T> std::vector<T> testClass::getData(int column){
    std::vector<T> returnData;
    return returnData;
}

template std::vector<int> testClass::getData(int column);
YugT
  • 13
  • 6
  • [Click](https://ideone.com/qgCspR) works well – kocica Aug 23 '17 at 09:34
  • [Cannot reproduce](http://coliru.stacked-crooked.com/a/3863947b2783a280). – YSC Aug 23 '17 at 09:35
  • Yes, I also just tested with GCC 7. – ypnos Aug 23 '17 at 09:35
  • Side note: Are you sure that it's the function, not the class that should be templated? – UKMonkey Aug 23 '17 at 09:36
  • Hmm... I use clang. And yes, it's the function. In the real implementation I need that function to return whatever I need. The actual class represents a whole bunch of different types of data. – YugT Aug 23 '17 at 09:37
  • Clang would compile that code just fine. Please [edit] your question to provide a [mcve]. Your compilation error comes from your code architecture I guess. – YSC Aug 23 '17 at 09:38
  • by doing t.getData(0), as you did on your second try, compiles for me on Visual Studio. Without the it says cannot deduce template type. – Zebrafish Aug 23 '17 at 09:39
  • As indicated in the answer, the problem was that I defined the function in a separate .cpp file.. Thanks for the helpful remarks people! – YugT Aug 23 '17 at 09:49

2 Answers2

1

Most likely your just defined your function template in a .cpp file instead of .h. That is why on t.getData<int>(0) you get a linker error. If that is the case, read this post.

WindyFields
  • 2,697
  • 1
  • 18
  • 21
0

I just ran the following program and it compiles fine.

#include <vector>

class testClass
{
public:
    template <typename T> std::vector<T> getData(int column);
};


template <typename T> std::vector<T> testClass::getData(int column){
    std::vector<T> returnData;
    return returnData;
}

int main()
{
    testClass t;
    std::vector<int> data = t.getData<int>(0);
    return 0;
}

With templates you should not be using a separate cpp file for the functions. Make sure you put the definition in the header file. This is necessary because any type can be passed in the template and the compiler will need to make a new version of the function for each different type. When dealing with templates I often just define my function inside the class.

class testClass
{
public:
    template <typename T> std::vector<T> getData(int column){
        std::vector<T> returnData;
        return returnData;
    }
};
chasep255
  • 11,745
  • 8
  • 58
  • 115
  • Sweet, thanks!! I indeed define the function in a separate cpp file. – YugT Aug 23 '17 at 09:47
  • Just as some extra info. If you do want to put your code in the cpp, you can add the specific implementation to your cpp file. It will then link. So in case of using let's say and int and a double add: – YugT Aug 23 '17 at 12:53
  • template std::vector testClass::getData(int column); template std::vector testClass::getData(int column); – YugT Aug 23 '17 at 12:54