Hi all,

I'm new to working with C++ (I'm more a C programmer) and I have a question:
I have a container class for a templated type T, which could be any scalar type, although the most commonly used ones are unsigned char and float.
I have a function that prints some of the elements to screen:

template <class T>
void dumpImageAscii(
    const Image2D<T> *image, 
    const char *file_name)
{
    ...
    bool is_int = numeric_limits<T>::is_integer;
    ....
    for (v = image->bounds._l2; v <= image->bounds._h2; v++)
    {
        for (u = image->bounds._l1; u <= image->bounds._h1; u++)
        {
            if (is_int)
                fprintf(pFile, "%10d", image->m[v][u]);
            else
                fprintf(pFile, "%16g", image->m[v][u]);
        }
        fprintf(pFile, "\n");
    }
   ....
}

Although the is_int flag takes care of formatting when printing, the compiler still throws a warning every time I call this function, stuff like:

warning: format ‘%10d’ expects type ‘int’, but argument 3 has type ‘double’

Which is expected because it's not smart enough to figure out which tree to go in at compile time.
I do not like seeing warnings in my code, especially unnecessary warnings like these...
Is there a way around this?
Also I want to avoid cout/fout whenever possible...most of the project is straight C, it's just that we need templates for this part.

Thanks.

Recommended Answers

All 5 Replies

better off replacing that fprintf() with c++ fstream class so that the compiler won't complain so much.

I understand for quick solutions you would follow AncientDragon's sage advice.
However, that always leaves a sour taste since I am sure your want to know how to do it:

So here goes

template<typename A>
struct printFunctor
{
   static void print(FILE*,const T& Obj) { }
};

template<>
struct printFunctor<int>
{
    static void print(FILE* fptr,const int& Obj) {  // stuff for int }
};
// and so on for each type

Then it is just printFunctor<T>::print(Fdata,image->m[v][u]); assuming that template object T exists, or you can write printFunctor<int>::print(Fdata,image->m[v][u]); as appropiate.

There are lots and lots and lots of cool variants of this principle.

commented: Thanks for the solution. +1

>I understand for quick solutions you would follow AncientDragon's sage advice.
Actually, AD's advice is ideal:

Student: "How do I use printf with templates in C++?"
Teacher: "Don't use printf."

The only reason the OP is using printf is because he's new to C++ and used to C. Giving a C++ beginner a template specialization solution alone is silly (you seriously thought that was a good idea?), but doing it to help him hack his way into some frankensteinish bastardization of C and C++ is STUPID!

>There are lots and lots and lots of cool variants of this principle.
Yes, there are. But this particular variant could go into the bit bucket without anyone shedding a tear.

Just a quick comment (again). The problem I though was not using printf. Yes I know that is not very C++ but if you need exact formated output, you normally end up at the boost::format class. That still needs separation of different type.

So you can write a quick functional separator (or use the boost::mpl) and then EVERY time you call the functional your get the correct version called. In addition, if you make a mistake and use a type that you have not schedules it for you get a compiler error which is EXACTLY what you want. [Since std::cout is often to accepting and boost::format is runtime.]

It doesn't make a lick of sense to write a custom print function for every conceivable data type using printf() or fprintf(). cout, ofstream and ifstream already have overloaded functions that do it for you. And formatting can be easily done using cout or fstream class.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.