2

Assuming this is my library. And it is a very huge library:

library.hpp

template<class usertype> void function_name(usertype aaa)
{
}

This is my main

int main()
{
    int x=3;
    function_name(x);
    double y=3.5;
    function_name(y);
    return 0;
}

I do not know what is going inside the library. What I want is to convert the library to adapt my code. In fact, reducing the template into real code.

I need the library code above be converted into:

void function_name(int aaa)
{
}

void function_name(double aaa)
{
}

So I can manipulate the library according to my needs instead of manipulating the general code that works for everybody. How can this conversion from template to real code be done (without manual effort, but in automatic way)?

Edit:

I want to convert the whole file library.hpp into library_2.hpp which contains no template. Instead with two real implemented functions. This is what happens in the middle of the compilation.

I am not looking for reducing the compilation time. I am dealing with a huge library made of 196 files. Among those many functions in the library, I will need a few of them related to my work. I intend to hack and extend this library. Extending the whole library has huge effort cost for me. I just want to extend only what I need. So, it is very important for me to reduce the code and simplify it and remove all templates replacing them with explicit code. I am not good at C++ and it compiler errors. So, in such a huge library, I prefer to use automatic methods rather than involving manual code manipulation. I am also not good at understanding this library. To understand the library, better to convert its complicated functions into explicit implemented code related to what I really need. Then I can understand someones else code better. I will remove the functions not related to my needs. I also do not care about updates coming to the library. Once I establish new library, its maintenance is my duty. And the new library would be much smaller and easier for maintenance. Comments show that some people looking at my aim from different view. I hope this explanation is clear.

In case of curiosity, the library I am going to manipulate is odeint related to mathematical computations with rarely change or bug inside.

barej
  • 1,330
  • 3
  • 25
  • 56
  • 5
    You might want to read about [template specialization](http://en.cppreference.com/w/cpp/language/template_specialization). – Some programmer dude Jan 14 '15 at 08:47
  • you can just use function_name (x) or function_name (y) – Irrational Person Jan 14 '15 at 08:49
  • I want to convert the library into a code that contains no template anymore. – barej Jan 14 '15 at 08:53
  • 1
    err, open an editor and have at it... there is no automatic way of doing this... – Nim Jan 14 '15 at 08:55
  • @Nim I deal with a library which contains at least 196 files. Seems to be impossilbe. – barej Jan 14 '15 at 08:58
  • not impossible, will take a really long time - which then begs the question - what exactly are you trying to achieve? Seems a pointless refactoring exercise - esp if the library works, may be you just need to look at the link pointed to by Joachim.. – Nim Jan 14 '15 at 09:00
  • @Nim, the problem is that you need to compile this code so many times at each file that you change. At each of them you will face with some compiler errors that you cant resolve. You know how much compiler errors related to templates are tough! The compiler converts this code. I am looking for a way to catch that simpler code generated in the middle of compilation process. – barej Jan 14 '15 at 09:04
  • @barej, it's unlikely that the compiler will convert the template code to "simple c++", it probably converts to it's own internal "syntax", which you probably won't be able to get (I'd imagine this is the case even with clang). Further more, you need to know every single explicit instantiation of the templates, which I'd imagine will be a nightmare. You could look at explicit instantiations (i.e. in an implementation file, explicitly instantiate some of the templates so that you can catch any errors early) but beyond that, if your current compiler is slow, upgrade is your only option.. – Nim Jan 14 '15 at 09:11
  • 1
    While it's nice to have fast build times, you have to offset that with what you're trying to achieve, and in this case it seems the time refactoring the code will be prohibitive compare to build times, not to mention that future use of the library may be limited because it's no longer generic, and future developer will probably refactor it back to use templates because it's better to have generic and open code that can be used for many cases, than specialized and narrow code for just a few cases. – Some programmer dude Jan 14 '15 at 09:33
  • Oh, and a note about your phrasing of the title, templated code is just as real as non-templated code. – Some programmer dude Jan 14 '15 at 09:34
  • @JoachimPileborg fixed the title. – barej Jan 14 '15 at 09:40
  • Somewhat related question: [Are there tools to transform source code in C++ to the source code in C/C++, but with instantiated (unrolled) templates?](http://stackoverflow.com/questions/15729585/are-there-tools-to-transform-source-code-in-c-to-the-source-code-in-c-c-but) – manlio Jan 14 '15 at 10:32
  • No idea *why* you want to have *real code*. I believe you are on the absolute wrong way! – Klaus Jan 14 '15 at 10:47
  • @manlio This is a great link you left as comment. The only problem is that all suggested methods generate many types of file but none of them is C++. – barej Jan 14 '15 at 10:57
  • @Klaus a simple answer is that I do not need those complicated templates. I need something simple. The library is very hard to understand and I dont know what each function does. converting templates into simple explicit code is the first step for simplifying the library. I use less 10% of the functionality of the library and I dont want to study the whole complicated functions of someones else code. – barej Jan 14 '15 at 11:00
  • @barej If you are using *composition* to build something new out of something existing, then you don't *need* to understand the whole complexity of someone else's code. This is the whole point of modularity. – 5gon12eder Jan 14 '15 at 11:02
  • 1
    Which function in odeint do you want to customize? – headmyshoulder Jan 14 '15 at 11:18
  • @headmyshoulder, I was thinking about contacting you. Maybe here is not a right place to discuss about it but I need that integrated_adaptive calls an external function at each 0.1 sec while calculation. related to model predictive control. – barej Jan 14 '15 at 11:21
  • Yeah, you can write my an email. My mail address is in the odeint source code (Karsten) :). – headmyshoulder Jan 14 '15 at 11:43

2 Answers2

2

I'm not entirely sure what you want to achieve but from reading the comments, I think that your major concern is that you are trying to reduce compile times and get less template-related error messages. You are not trying to specialize library functions for your own types.

If you only instantiate the templated functions from the library with a handful of types, there is a simple recipe to get templates out of your picture. But it will force you to write two lines of code for each combination of templated function and type you want to use it with.

Create your own header file library_wrapper.hpp. There, you declare non-template versions of the functions you want to use.

library_wrapper.hpp

#ifndef LIBRARY_WRAPPER_H
#define LIBRARY_WRAPPER_H

#include <vector>  // just an example

namespace library_wrapper
{
  void
  function_name(int);

  void
  function_name(double);

  int
  another_function(const std::vector<double>&, bool);
}

#endif

And then “implement” them once and for all using your so-little-loved template library.

library_wrapper.cpp

#include "library_wrapper.hpp"
#include <library.hpp>  // the template library

namespace library_wrapper
{
  void
  function_name(const int arg1)
  {
    return library::function_name(arg1);
  }

  void
  function_name(const double arg1)
  {
    return library::function_name(arg1);
  }

  int
  another_function(const std::vector<double>& arg1, const bool arg2)
  {
    return library::function(arg1, arg2);
  }
}

You compile library_wrapper.cpp once, fight the templates, and then continue using only your wrapper which provides the non-templated functions.

Be aware that this approach jeopardizes one of the major reasons templates can be so fast: inlining. Your wrapper functions cannot be inlined at compile-time because you are hiding their definitions from the compiler. This is on purpose and, on the other hand, buys you shorter compile times. Link-time inlining might give you some inlining back but you shouldn't take it as granted.

Note that this solution does not work quite as well with types (as opposed to functions). You could try writing some pimpl-wrappers but I don't recommend this. Maybe the best thing would be to become friends with your template library…

Update addressing your updated question

I am dealing with a huge library made of 196 files. Among those many functions in the library, I will need a few of them related to my work.

In case of curiosity, the library I am going to manipulate is odeint related to mathematical computations with rarely change or bug inside.

This seems like the above approach could indeed help.

Extending the whole library has huge effort cost for me. I just want to extend only what I need. So, it is very important for me to reduce the code and simplify it and remove all templates replacing them with explicit code.

I don't think that this is a good approach. Instead, use the library as a black box and build your own on top of it. Concentrate your developer effort on the new features and benefit from updates for the underlying library.

I assume that the library in question is free software (otherwise, what you want to do would be illegal anyway) and free software project should support each other. If you are building an awesome library Y on top of library X, both projects, X and Y, can benefit. On the other hand, if you rip out only a part of that other library and add other functionality, your two rivalling projects might both end up as something incomplete and incompatible which is frustrating for both, you and your users.

To understand the library, better to convert its complicated functions into explicit implemented code related to what I really need. Then I can understand someones else code better.

I don't think that you can reasonably expect that some machine-generated code will be more readable than the original human-written code of the library. After all, human coders are taught to write code for humans but compilers are optimized for other aspects.

I am not good at C++ and it compiler errors. […] I am also not good at understanding this library.

I intend to hack and extend this library.

I also do not care about updates coming to the library. Once I establish new library, its maintenance is my duty.

I don't want to seem rude but … do you see the problem?

Community
  • 1
  • 1
5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • Thank you. I updated the question adding some explanations at the end. – barej Jan 14 '15 at 10:27
  • In fact, I am specializing the library functions for my own types too. This library does not allow me to implement some mathematical functionalities. So, hacking the library is inevitable. Also, I do not need to change it in a way to work for all types of numbers. I just need to use it for especial matrix types that is known to me. – barej Jan 14 '15 at 11:02
  • The software is free. But i need to change it for a university project. Its application is very limited however no problem with sharing it. But I dont want to extend the library to work for all types. So need to remove the templates. I finally can handle C++ compiler error challenges as far as it is not related to templates. It gives me good reason to escape templates. If there is a way, why not escaping. Readability of machine generated code is not a big deal to me. I can put both codes next to each other. – barej Jan 14 '15 at 11:11
0

by specialization

template<>
void function_name(int aaa)
{
}

template<>
void function_name(double aaa)
{
}

sample code

#include <iostream>
template<class usertype>
void function_name(usertype aaa)
{
    std::cout << "default\n";
}

template<>
void function_name(int aaa)
{
    std::cout << "int value = " << aaa << '\n';
}

template<>
void function_name(double aaa)
{
    std::cout << "double value = " << aaa << '\n';
}

int main()
{
    int x = 3;
    function_name(x);
    double y = 3.5;
    function_name(y);
    struct Z{} z;
    function_name(z);
    return 0;
}
MORTAL
  • 383
  • 2
  • 10
  • What is the range of those specializations ? – Quentin Jan 14 '15 at 10:03
  • Often given advice is to avoid specializing function templates and use overloading instead. It avoids bad surprises if the library already contains an overload that is a template itself. – 5gon12eder Jan 14 '15 at 10:14
  • @5gon12eder .. agree i was wondering why the specialization not recommend so often and the SFINAE is an alternative choice. but SFINAE is bit complicated and introduced lately in C++11 most of people wouldn't comfortable to use it yet. – MORTAL Jan 14 '15 at 10:28
  • @Quentin .. the range can be extended to all types – MORTAL Jan 14 '15 at 10:32
  • The reason that specialization of function templates is discouraged is that it can become very confusing if mixed with overloading that looks like partial specialization (which doesn't exist). See [The Dimov/Abrahams Example](http://www.gotw.ca/publications/mill17.htm). – 5gon12eder Jan 14 '15 at 10:32
  • @MORTAL I mean, IINM once these specializations exist in a translation unit they will be picked up by anything compiled along. Thus OP's need not to disturb other users seems not to be fulfilled. – Quentin Jan 14 '15 at 10:37
  • @Quentin .. it can be guarded by namespace if that a case. – MORTAL Jan 14 '15 at 10:41