0

I'm getting undefined reference to ´long long fromBigEndin<long long>(unsigned char*)´ for a template specialization.

See code here: https://onlinegdb.com/AagKTQJ2B

I have this structure:

util.h

template <class T>
T fromBigEndin(uint8_t *buf);

template <>
int64_t fromBigEndin<int64_t>(uint8_t *buf);
template <>
long long fromBigEndin<long long>(unsigned char *buf);

util.cpp

template<class T>
T fromBigEndin(uint8_t *buf) {
    T number = 0;
    uint8_t nBytes = sizeof(T);
    uint8_t i;

    for (i = 0; i < nBytes; i += 1) {
        number += buf[i] << (16 * (nBytes - i - 1));
    }

    return number;
}

headerImpl.h

#include "util.h"

void handleOpenSession(uint8_t *data) {
    uint8_t *uid = (uint8_t *)malloc(8);
    memcpy(uid, data + 1, 8);
    int64_t uidNbr = fromBigEndin<int64_t>(uid);
}

From @AnoopRana response, putting the implementation in header file works, I would like to know if it is possible to put the implementation in a separate file.

Any idea on how could I force the compilation of fromBigEndin<int64_t>()?

I've also tried to move the specializations to util.cpp but doesn't work either.

The code itself works when in a single file and with different declarations:

Miquel
  • 8,339
  • 11
  • 59
  • 82
  • Seems for classes it it possible: https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file, what I'm asking is if it is possible to do it with functions – Miquel May 21 '22 at 17:38
  • Method 2 works now. I have updated the example. Earlier i made small typo in method 2 so that's why it were' working. See [demo method 2](https://onlinegdb.com/wiuwROG4f) – Jason May 21 '22 at 18:08

1 Answers1

1

Method 1

You need to put the implementation of the function template into the header file itself. So it would look something like:

util.h

#pragma once  //include guard added
template <class T>
T fromBigEndin(uint8_t *buf);

//definition
template <> int64_t fromBigEndin<int64_t>(uint8_t *buf)
{
    return 53;
}
//definition 
template <> long long fromBigEndin<long long>(unsigned char *buf)
{ 
    return 54;
}


//implementation in header file itself
template<class T>
T fromBigEndin(uint8_t *buf) {
    T number = 0;
    uint8_t nBytes = sizeof(T);
    uint8_t i;

    for (i = 0; i < nBytes; i += 1) {
        number += buf[i] << (16 * (nBytes - i - 1));
    }

    return number;
}

headerImpl.h

#pragma once
#include "util.h"

void handleOpenSession(uint8_t *data) {
    //add code here 
}

main.cpp

#include <iostream>
#include "util.h"
int main()
{
    
    return 0;
}

Working demo

Method 2

Here we make use of explicit template instantiations.

util.h

#pragma once
#include <cstdint>
template <class T>
T fromBigEndin(uint8_t *buf);


headerImpl.h

#pragma once
#include "util.h"


void handleOpenSession(uint8_t *data) {
    uint8_t *uid = (uint8_t *)malloc(8);
    memcpy(uid, data + 1, 8);
    int64_t uidNbr = fromBigEndin<int64_t>(uid);
}

util.cpp

#include "util.h"

template<class T>
T fromBigEndin(uint8_t *buf) {
    T number = 0;
    uint8_t nBytes = sizeof(T);
    uint8_t i;

    for (i = 0; i < nBytes; i += 1) {
        number += buf[i] << (16 * (nBytes - i - 1));
    }

    return number;
}

//no angle brackets used here
template int64_t fromBigEndin<int64_t>(uint8_t *buf);
template long long fromBigEndin<long long>(unsigned char *buf);

main.cpp


#include <iostream>

#include "util.h"
int main()
{
    
    return 0;
}

Working demo

Jason
  • 36,170
  • 5
  • 26
  • 60
  • Yes, this works, but I'm trying to put the implementation on a cpp separate file. From what I've seen it seems possible to put it separated, if it is not, I will accept this solution – Miquel May 21 '22 at 17:30
  • This is the question, when I try method 2, it fails with `undefined reference` – Miquel May 21 '22 at 17:51
  • If you try it, it does not work – Miquel May 21 '22 at 17:58
  • I have the demo, but cannot save (don't have an account) I will save in brief – Miquel May 21 '22 at 18:00
  • Check method 2 error here: https://onlinegdb.com/AagKTQJ2B – Miquel May 21 '22 at 18:02
  • @Miquel I made a small typo while writing method 2. [Here](https://onlinegdb.com/hYABMh6eS) is the updated link. Note there should be no angle brackets as commented in my demo example. – Jason May 21 '22 at 18:06