Anil Kumar Martha
Anil Kumar Martha

Reputation: 67

Shared library with template parameters

Created shared library with below file

example.cpp
#include <iostream>
template <typename T>
T  Max (T & a, T & b) 
{ 
    return a < b ? b:a; 
} 

I was trying to use above library in my code

test.cpp
#include <stdio.h>
#include <iostream>
using namespace std;

template int  Max <int> (int & a, int & b);
template double  Max <double> (double & a, double & b);

int main ()
{
    int i = 39;
    int j = 20;
    cout << "Max(i, j): " << Max(i, j) << endl; 
    double f1 = 13.5; 
    double f2 = 20.7; 
    cout << "Max(f1, f2): " << Max(f1, f2) << endl; 
    return 0;
}

when I compiled above code ,getting the following error

test.cpp:4: error: explicit instantiation of non-template ‘int Max’
test.cpp:4: error: expected ‘;’ before ‘<’ token
test.cpp:5: error: explicit instantiation of non-template ‘double Max’
test.cpp:5: error: expected ‘;’ before ‘<’ token
test.cpp: In function ‘int main()’:
test.cpp:11: error: ‘Max’ was not declared in this scope*

Upvotes: 4

Views: 1456

Answers (2)

WhozCraig
WhozCraig

Reputation: 66194

I realize this is a trivial example more for academic purpose than anything else. Otherwise I would recommend scrapping the whole thing and just using std::max from the get-go. The standard library provides a wealth of well-specified and tested functionality for the taking; use it unless you have a damn good reason to reinvent the wheel.

If you seriously want to provide a template declaration of a function in a header, and provide the implementation of said-template in a shared object library, you can do it by using explicit instantiation, which it appears you're attempting. However, your attempt appears to be putting said-same in the wrong module.

One way to do it is as follows:

example.hpp

#ifndef MYLIB_EXAMPLE_HPP
#define MYLIB_EXAMPLE_HPP

// define forward declaration here. no implementation
template<class T> T Max(T lhs, T rhs);

#endif

example.cpp

#include "example.hpp"

// provide implementation here    
template<class T>
T Max(T lhs, T rhs)
{
    return (lhs < rhs) ? rhs : lhs;
}

// explicit instantiations
template int Max<int>(int,int);
template double Max<double>(double,double);

That's it for the library. An example build using clang would be:

clang++ -std=c++11 -Wall -Wextra -pedantic -fPIC -shared -o libexample.so example.cpp

The resulting shared object library exposes the following symbols:

nm libexample.so

0000000000000f50 T __Z3MaxIdET_S0_S0_
0000000000000f20 T __Z3MaxIiET_S0_S0_
                 U dyld_stub_binder

so as you can see, they're there in the lib. On to the test program that will consume this library:

test.cpp

#include <iostream>
#include "example.hpp"

int main ()
{
    int i = 39;
    int j = 20;

    std::cout << "Max(i, j): " << Max(i, j) << std::endl;

    double f1 = 13.5;
    double f2 = 20.7;

    std::cout << "Max(f1, f2): " << Max(f1, f2) << std::endl;

    return 0;
}

We build it as follows (assuming the library is in the local folder):

clang++ -std=c++11 -Wall -Wextra -pedantic -L. -o test -lexample test.cpp

The resulting program, test, produces the following output:

Max(i, j): 39
Max(f1, f2): 20.7

Honestly, there isn't a ton of value in doing it this way, as any future usages of Max that are not provided in your explicit list will result in linker errors (unless that is the intent, in which case it would do exactly what you're looking for).

Upvotes: 6

R2-Dequeue
R2-Dequeue

Reputation: 638

My recomendations:

  • Change example.cpp to header a file, Max is a template function
  • Remove the forward declarations in the code
  • Remove #include <stdio.h>, unless that really is used somewhere

example.hpp:

template <typename T>
T Max (T& a, T& b)
{
    return a < b ? b : a;
}

test.cpp:

#include <iostream>

using namespace std;

int main ()
{
    int i = 39;
    int j = 20;

    cout << "Max(i, j): " << Max(i, j) << endl;

    double f1 = 13.5;
    double f2 = 20.7;

    cout << "Max(f1, f2): " << Max(f1, f2) << endl;

    return 0;
}

Upvotes: 1

Related Questions