4

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*
Barry
  • 286,269
  • 29
  • 621
  • 977
  • You can safely delete `test.cpp` lines 3 - 4, unless you're going to specialize the function definition for `double` or `int`. – Daniel Robertson Jul 30 '15 at 16:25
  • it isn't clear what you're *really* trying to accomplish in question? Are you trying to implement a template function and provide only a specific set of explicit instantiations in a shared object library? If so, it is doable, but some rearrangement of your code is required. If all you want to do is implement a template function the shared object library isn't required and the implementation should be done in a header-only. – WhozCraig Jul 30 '15 at 17:11
  • 1
    If the goal is strictly to compare for max, you should probably use `std::max` instead of a custom template unless you need a variadic version. Templates generally need to be defined in header files though, since the compiler uses them to generate code. – Jason Jul 30 '15 at 17:25

2 Answers2

6

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).

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
1

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;
}
R2-Dequeue
  • 638
  • 1
  • 5
  • 15