11

Templates can be programs in themselves.

Is there a template debugger so you can step thru the "execution" of the template?

This would basically have to be something that is done during compile/link/codegen - and is distinct from debugging the generated program.

Even in many "primitive" environments where you cannot use a debugger, you can usually do "printf debugging". Is even that possible with templates?

edit: Another way to think about this is something like the C preprocessor. It is often very useful to generate "preprocessed" source code - the output from the preprocessor that the compiler is actually compiling - this lets you see what effect your macros are having. A template equivalent would be great - have the compiler output the non-template source code which cooresponds to the templated input. The closest you can get I suppose is a C++ to C translator. (Doesn't the comeau compiler do this?)

joeking
  • 2,006
  • 18
  • 29
  • There are some tools but I have not tried so I don't really know what they do or how well they do it. You can look into [TempLight](https://github.com/sabel83/templight) or [metashell](https://github.com/sabel83/metashell) – David Rodríguez - dribeas Oct 14 '14 at 17:18
  • I can't answer the question of "stepping through" template compilation, but as far as "printf-style debugging", you can use preprocessor directives to print custom comments or warnings to the build output. http://stackoverflow.com/questions/3826832/is-there-a-portable-way-to-print-a-message-from-the-c-preprocessor – iwolf Oct 14 '14 at 17:24
  • Not really related: *After* the type has been deduced, you can use `typeid` to get its (mangled) name. – edmz Oct 14 '14 at 17:44
  • @black that may not always be a good idea as [argued here](http://youtu.be/wQxj20X-tIU?t=48m1s) – PeterT Oct 14 '14 at 17:52
  • black: Yeah, I've done that. Different compilers have different ways of providing de-mangled names as well. (General gripe about the C++ standard: The standard doesn't consider debuggability nearly enough - there oughta be a standard defined way to get the demangled name for instance). This, and other techniques, require you to edit the source code, making guesses about whats happening during compile time to make good choices about where to insert errors or typeid() things. – joeking Oct 14 '14 at 19:34
  • iwolf: I don't think this helps with templates much - it lets you see which source files are compiled, but doesn't let you follow along as the compiler expands templates. – joeking Oct 14 '14 at 19:35
  • @joeking Take a look at [metashell](https://github.com/sabel83/metashell). The interactive environment is a useful learning tool. I am not sure what the support for full-fledged files and projects is. – Pradhan Dec 29 '14 at 20:37

2 Answers2

4

You might want to look at this patch for clang that outputs template instantiations.

Another simple tool is the error messages your compiler produces for attempting to instantiate an undefined template.

template< typename > struct TD;

template< typename T >
void your_template_function( T & param )
{
    // Both of these produce an error about "undefined type TD< T > with T = ..."
    TD< T > test1;
    TD< decltype( param ) > test2;
}

This is explained in Scott Meyers CPPCon talk, right after the ring-tailed lemur slide.

Khouri Giordano
  • 1,426
  • 15
  • 17
2

On the last years c++ conference there was a talk to that topic. Some of the informations you can find here:

http://gsd.web.elte.hu/contents/articles/gpce06.pdf

and

http://patakino.web.elte.hu/ECOOP_Templight_Poster.pdf

I have no idea how functional that stuff now is, but it was a very interesting startpoint.

I personal wrote me some helper classes which are able to print me the given types like printf debugging for standard code. If the compilation fails it often gives a good error message while calling the DebugPrinter and if the program compiles but the result is really stupid because the type expansion is not what I expect the DebugPrinter helps me a lot!

    template< typename T>
int DebugPrintArgs( T arg )
{
    std::cout << arg  << ", ";
    return 0;
}

template <typename Head, typename ... T>
class DebugPrinter: public DebugPrinter<T...>
{
    public:
        DebugPrinter()
        {
            std::cout << "--------------------------" << std::endl;
            std::cout << __PRETTY_FUNCTION__ << std::endl;
            std::cout << "--------------------------" << std::endl;
        }

        template< typename ...Y>
            DebugPrinter( Y ... rest )
            {
                std::cout << "Construction of: " << __PRETTY_FUNCTION__ << " Values: " ;
                ExpandWithConstructor{DebugPrintArgs( rest)...};
                std::cout << std::endl;
            }

};


template <typename Head>
class DebugPrinter< Head >
{
    public:
        DebugPrinter()
        {
            std::cout << "--------------------------" << std::endl;
            std::cout << __PRETTY_FUNCTION__ << std::endl;
            std::cout << "--------------------------" << std::endl;
        }
};
Klaus
  • 24,205
  • 7
  • 58
  • 113