views:

396

answers:

4

When I try to use float as a template param, the compiler cries for this code, while int works fine. Is it that I cannot use float as a template parameter?

#include<iostream>
using namespace std;

template <class T, T defaultValue>
class GenericClass
{
private:
    T value;
public:
    GenericClass()
    {
        value = defaultValue;
    }

    T returnVal()
    {
        return value;
    }
}; 


int main()
{
    GenericClass <int, 10> gcInteger;
    GenericClass < float, 4.6f> gcFlaot;

    cout << "\n sum of integer is "<<gcInteger.returnVal();
    cout << "\n sum of float is "<<gcFlaot.returnVal();

    return 0;       
}

Error:

somthing.cpp: In function `int main()':
somthing.cpp:25: error: `float' is not a valid type for a template constant parameter
somthing.cpp:25: error: invalid type in declaration before ';' token

somthing.cpp:28: error: request for member `returnVal' in `gcFlaot', which is of non-class type `int'

I am reading "Data Structures for Game Programmers" by Ron Penton, the author passes a float, while when I try it it doesn't seem to compile.

+6  A: 

The current C++ standard does not allow float (i.e. real number) or character string literals to be used as template constant parameters. You can of course use the float and char * types as normal parameters. Perhaps the author is using a compiler that doesn't follow the current standard?

anon
+2  A: 

I think it's the type of defaultValue that is causing the problem, rather than the type itself. The following compiles fine with g++:

#include <iostream>

using namespace std;

template <class T>
class GenericClass
{
private:
    T value;
public:
    GenericClass()
    {
    }

    T returnVal()
    {
        return value;
    }
}; 

int main()
{
    GenericClass <int> gcInteger;
    GenericClass <float> gcFlaot;

    cout << "\n sum of integer is " << gcInteger.returnVal();
    cout << "\n sum of float is " << gcFlaot.returnVal();

    return 0;       
}
Paul R
+4  A: 

Indeed, you can't use float literals as template parameters. See section 14.1 ("A non-type template-parameter shall have one of the following (optionally cv-qualified) types...") of the standard.

You can use a reference to the float as a template parameter:

template <class T, T const &defaultValue>
class GenericClass

.
.

float const c_four_point_six = 4.6; // at global scope

.
.

GenericClass < float, c_four_point_six> gcFlaot;
moonshadow
You can. but it doesn't do the same thing. You can't use the reference as a compile-time constant.
anon
+3  A: 

Just to provide one of the reasons why this is a limitation (in the current standard at least).

When matching template specializations, the compiler matches the template arguments, including non-type arguments.

By their very nature, floating point values are not exact and their implementation is not specified by the C++ standard. As a result, it is difficult to decide when two floating point non type arguments really match:

template <float f> void foo () ;

void bar () {
    foo< (1.0/3.0) > ();
    foo< (7.0/21.0) > ();
}

These expressions do not necessarily produce the same "bit pattern" and so it would not be possible to guarantee that they used the same specialization - without special wording to cover this.

Richard Corden