Another easy one

Ok, I'm trawling through the tutorials, and have got to templates, the syntax of which is a little baffling, although the concept reasonably straightforward. I had this test question below, can you tell me why the right answer is the right answer! TIA.

Which of the following is an invalid template declaration:

a) template <int x> int func() {return x;}
b) template <double x> double func() {return x;}
c) template <typename x> void func(x t) {}
I honestly don't know the answer to this one. =x If I had to guess I'd say B, only because double is a nonintegral type and maybe C++ templates don't like that. But I don't know for sure.

On a somewhat related note: I never understood the point of using variables as template parameters (like a or b in your example -- what's the point?). I mean why not just pass them as a function/ctor parameter. Does anyone know why they'd be benefitial?
My guess.
b is wrong because only integer (integral) types are are allowed is template decalartions like that (see example a).
B.

@Disch:

One example I use quite often:

1
2
3
template< typename T, size_t N >
size_t ArraySize( T (&)[ N ] )
{ return N; }


is a handy way of computing the size of a fixed length array without having to create a #define or const for it.

Another (simplistic) example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template< typename T, size_t N >
size_t asize( T (&)[ N ] )
{ return N; }

template< typename T, size_t N >
T* abegin( T (&a)[ N ] )
{ return a; }

template< typename T, size_t N >
T* aend( T (&a)[ N ] )
{ return a + N; }

//And now this works:
static int int_array[] = { 1, 2,3, 4, 5, 6, 7, 8, 9, 10 };
std::cout << std::accumulate( abegin( int_array ), aend( int_array ), 0 );


well, yes, the answer is b) but sadly I'm non the wiser as to why?

or sizeof (array) / sizeof (array[0]); C, I know, but seems a lot simpler than the stuff above, well to me anyway !
Last edited on
From C++ Templates - the complete guide book 4.3 Restrictions for Nontype Template Parameters
Note that nontype template parameters carry some restrictions.
In general, they may be constant integral values (including enumerations) or
pointers to objects with external linkage.

Floating-point numbers and class-type objects are not allowed as nontype template parameters:

template <double VAT> // ERROR: floating-point values are not
double process (double v) // allowed as template parameters
{
return v * VAT;
}

template <std::string name> // ERROR: class-type objects are not
class MyClass { // allowed as template parameters

};
Not being able to use floating-point literals (and simple constant floating-point expressions)
as template arguments has historical reasons. Because there are no serious technical
challenges, this may be supported in future versions of C++ (see Section 13.4 on page 210).



Last edited on
@twoscoops:

It is arguably simpler to understand how the sizeof method works, but it is not simpler to use, and it is definitely much more prone to misuse. Example:

1
2
3
4
5
6
7
8
9
int main() {
    int* parray = new int[ 10 ];

    // Compiles, but gives wrong answer (runtime bug)
    std::cout << "Size of array is " << (sizeof(parray)/sizeof(parray[0]));

   // Does not compile (compile time bug)
   std::cout << "Size of array is " << ArraySize( parray );
}


I'd rather have compile time bugs than runtime bugs.
Last edited on
Nah, gives exactly the right answer! sizeof of a pointer / sizeof of first element. Simples.
From C++ Templates - the complete guide book
4.3 Restrictions for Nontype Template Parameters
Note that nontype template parameters carry some restrictions.
In general, they may be constant integral values (including enumerations) or
pointers to objects with external linkage.

Floating-point numbers and class-type objects are not allowed as nontype template parameters:

template <double VAT> // ERROR: floating-point values are not
double process (double v) // allowed as template parameters
{
return v * VAT;
}

template <std::string name> // ERROR: class-type objects are not
class MyClass { // allowed as template parameters

};
Not being able to use floating-point literals (and simple constant floating-point expressions)
as template arguments has historical reasons. Because there are no serious technical
challenges, this may be supported in future versions of C++ (see Section 13.4 on page 210).


template <double VAT>

I don't understand why this is a template? As it is specifying the type....... v confused.


template <double VAT>

I don't understand why this is a template? As it is specifying the type....... v confused.


The 'template' keyword is a dead givaway =P

</wiseass>

Template declarations are the same as non-template declarations, only they're prefixed by the template keyword (and any template arguments).

IE:

1
2
3
4
5
6
// a non-template function
void foo(int bar) { }

// a template function
template <typename T>
void foo(T bar) { }


Syntax for each is exactly the same, but the template keyword slips in before the rest (even before the return type). That is what makes it a template.

But again note that you can't use double as a template parameter.
No, sorry, doesn't make any sense whatsoever.

template <int x> int func() {return x;} This is apparently a template, why?
template <double x> double func() {return x;} this is not even legal, why? apart from undefined historical reasons.

Now I can understand why this :-

template <typename T> is a template as we haven't defined the type

But the two at the top, why bother with the word template??

1) func returns and int and takes no parameters, what else can it do? what flexibility does the template <int x> do ?
2) Not even legal, but why oh why, just dump the template <double x> specifier.
You are right, the first two (the second one if legal) are pointless. There is no need for the template.
Topic archived. No new replies allowed.