I was tinkering around with code in C++ last night trying to make a template algorithm that would be evaluated at compile time and also print information.

Unfortunately, because std::cout and std::cin are references to objects and they aren't considered built in types (directly at least), I suppose the compiler considers them variable and not a "constant expression," so statements like the following--

template<int N>
class PrintInfo{

       enum {RESULT = ((std::cout << N << (N == 1) ? std::endl : std::flush ) , N) + PrintInfo<N-1>::RESULT};

};

template<>
class PrintInfo<0>{

      enum {RESULT = 0};

};

--are unallowed.

The same problem occurs if I try to specify a reference (or pointer) argument to the template, as well as pointer to function... etc. Basically anything that cannot be resolved at compile time due to its chance to vary will be unworkable.

What I'd like is a way to print the information at compile-time. I know for a fact that if the compiler is capable of doing parsing and optimizations during compile-time, it can at least flag what it is doing (possibly) in the error-window.

I'm using Microsoft Visual 2005/2008 compiler, on Windows XP.

-Alex

>flush is a function so you need to use () cout.flush()
std::flush is a manipulator, that part was fine.

>Try this macro
That still won't work as the construction is illegal.

>What I'd like is a way to print the information at compile-time.
That brings up the question of where and how you intend to print it. At compile-time you can really only rely on compiler-specific methods for outputting compile-time messages. You can get close with something like this:

#include <iostream>

#define STR(x) #x
#define TOSTRING(x) STR(x)

template <int N>
struct PrintInfo {
  enum { 
#pragma message(TOSTRING(N))
    RESULT = N + PrintInfo<N - 1>::RESULT 
  };
};

template<>
struct PrintInfo<0> {
  enum {
#pragma message("0")
    RESULT = 0
  };
};

int main()
{
  int result = PrintInfo<5>::RESULT;

  std::cout<<"Result: "<< result <<'\n';
}

But, because the preprocessor runs before template instantiation, you'll only see a bunch of N's rather than the actual value of N for each instantiation.

I'm not a template metaprogramming guru, so the only way I can think of to get a good compile-time output of each value of N is to specialize all of the values:

#include <iostream>

template <int N>
struct PrintInfo {
  enum {
    RESULT = N + PrintInfo<N - 1>::RESULT
  };
};

template<>
struct PrintInfo<0> {
  enum {
#pragma message("0")
    RESULT = 0
  };
};

template<>
struct PrintInfo<1> {
  enum {
#pragma message("1")
    RESULT = 1
  };
};

template<>
struct PrintInfo<2> {
  enum {
#pragma message("2")
    RESULT = 2 + PrintInfo<1>::RESULT
  };
};

template<>
struct PrintInfo<3> {
  enum {
#pragma message("3")
    RESULT = 3 + PrintInfo<2>::RESULT
  };
};

template<>
struct PrintInfo<4> {
  enum {
#pragma message("4")
    RESULT = 4 + PrintInfo<3>::RESULT
  };
};

template<>
struct PrintInfo<5> {
  enum {
#pragma message("5")
    RESULT = 5 + PrintInfo<4>::RESULT
  };
};

int main()
{
  int result = PrintInfo<5>::RESULT;

  std::cout<<"Result: "<< result <<'\n';
}

That defeats the purpose, of course. :icon_rolleyes: If you drop the compile-time output requirement and allow less than optimal construction of the result as you print, you can do this:

#include <iostream>

template <int N>
struct PrintInfo {
  enum { RESULT = N + PrintInfo<N - 1>::RESULT };

  static inline int run_debug()
  {
    std::cout<<"N = "<< N <<'\n';
    return N + PrintInfo<N - 1>::run_debug();
  }
};

template<>
struct PrintInfo<0> {
  enum { RESULT = 0 };

  static inline int run_debug()
  {
    return 0;
  }
};

int main()
{
#ifdef DEBUG
  // Inefficient for debugging
  int result = PrintInfo<5>::run_debug();
#else
  // Efficient for production
  int result = PrintInfo<5>::RESULT;
#endif

  std::cout<<"Result: "<< result <<'\n';
}

That gives you output of the instantiations while still generating the value. Each member function will ultimately be called though, so run_debug isn't going to give you the same compile-time constant as RESULT in the final machine code. That's why I left RESULT in there for when you don't want the output any longer.

Comments
Simply amazing... =)

>Try this macro
That still won't work as the construction is illegal.

Would you mind explaining why this is illegal? I'm probably wrong but it looks fine to me

>Would you mind explaining why this is illegal?
The short answer is that it's not a constant expression, which is required.

This article has been dead for over six months. Start a new discussion instead.