What Does Template <Unsigned Int N> Mean

What does template unsigned int N mean?

It's perfectly possible to template a class on an integer rather than a type. We can assign the templated value to a variable, or otherwise manipulate it in a way we might with any other integer literal:

unsigned int x = N;

In fact, we can create algorithms which evaluate at compile time (from Wikipedia):

template <int N>
struct Factorial
{
enum { value = N * Factorial<N - 1>::value };
};

template <>
struct Factorial<0>
{
enum { value = 1 };
};

// Factorial<4>::value == 24
// Factorial<0>::value == 1
void foo()
{
int x = Factorial<4>::value; // == 24
int y = Factorial<0>::value; // == 1
}

templates int T C++

Template parameters may be of any of the three kinds of C++ entities: values, types, or templates:

template <int N> struct Foo;                        // N is a value

template <typename T> struct Bar; // T is a type

template <template <typename> class X> struct Zip; // X is a template

Example usage:

Foo<10> a;

Bar<int> b;

Zip<Bar> c;

Note that this corresponds to the three ways of disamiguating dependent names:

X::a = 10;              // X::a is a value
typename X::B n = 10; // X::B is a type
X::template C<int> m; // X::C is a template

An interesting combination arises when you want to "typify" a value. This can be done like so:

template <typename T, T Val> struct Typificate;

Now you can say e.g. Typificate<int, 10> to get a unique type that represents the integer 10. This can occasionally be very useful, e.g. when T is a member function pointer (e.g. in this delegate implementation); or it can be used to create value-unique overloads for tag dispatch, etc.

why we need template int N since we have class initialization

The size of a class must be known at compile-time. So you can't provide the size at class initialization time. This includes the size of any fixed-sized arrays included in the class.

To confuse matters there are some compiler extensions that allow you to use the syntax of fixed-size arrays with dynamically allocated size but this is not standard C++.

Even classes like std::vector have a fixed size but they use dynamic memory allocation for their contents so the size of the contents can be provided at class initialization time. Such containers contain a pointer to the dynamically allocated memory instead of a fixed-size array.

Can a template parameter be both an int and an unsigned long?

From [temp.deduct.type]:

If P has a form that contains <i>, and if the type of i differs from the type of the corresponding template parameter of the template named by the enclosing simple-template-id, deduction fails.

A<N> for N is an int should fail deduction because the corresponding template parameter of A is actually size_t. This is a compiler #1 bug.

C++ template what does this class assignment in template mean?

LowerBound is a member template function declared inside the class template MyClass. It's similar to a function template but it is enclosed in a class (template).

The code can be simplified as

template <typename T>
class MyClass {

template <typename T1 = T, typename = std::enable_if_t<std::is_same<T1, int>{}>>
IndexValueType LowerBound(KeyType k) const {}
};

The first assignment T1 = T means the default argument for the first template parameter is the same type of T. If you are not explicitly specified, T1 will be T. You could of course explicitly specify other types.

The second assignment here is an usage of std::enable_if. Also pointed in the comments, it's a simple way to apply SFINAE. Here it will disable(ignore) templates when T1 is not the same as int. Since the second parameter is only to restrict the first parameter and has no usage in the definition, its name is ignored.

MyClass<int> mc1; // T is int
mc1.LowerBound(...) // T1 is int, when not specified explicitly
mc1.LowerBound<std::int32_t>(...) // T1 is std::int32_t here
MyClass<double> mc2; // T is double
mc2.LowerBound<int>(...) // OK, T1 is int
mc2.LowerBound(...) // T1 is substitued with double here and will cause compile error since is not int

In a template argument, what rules allow the compiler to infer the number of items of an array?

Template argument deduction is covered by [temp.deduct] [emphasis mine]:

/1 When a function template specialization is referenced, all of the
template arguments shall have values. The values can be explicitly
specified or, in some cases, be deduced from the use or obtained
from default template-arguments.

/2 (... regarding explicit template argument list: not relevant here)

/3 After this substitution is performed, the function parameter type
adjustments described in [dcl.fct] are performed. [ Example: A
parameter type of
“void (const int, int[5])” becomes
“void()(int,int)”. — end example ] [...]

Note the reference to [dcl.fct] and the related (non-normative) example in /3, showing the adjustment of a value type array function parameter int[N] to int*, meaning a non-type template parameter N is not deducible from arguments passed to a value type array parameter (N is useless/ignored in this context).

Template argument deduction from a function call, particularly, is covered by [temp.deduct.call]; and the relevant section that differentiates your two examples is [temp.deduct.call]/2.1, which says that if the argument of a call (denoted A) is an array type, and the parameter type (denoted P) is not a reference type, a pointer type is used for type deduction:

/2 If P is not a reference type:

  • (2.1) If A is an array type, the pointer type produced by the array-to-pointer standard conversion is used in place of A for type
    deduction; otherwise, [...]

Whereas when P is a reference type, as in the following example:

template<class T, std::size_t n>
std::size_t len(T (&v)[n]) { return n; }

[temp.deduct.call]/2.1 does not apply, and for the following call to a function named len with an array as argument

int arr[] = { 1,2,3 };
(void)len(arr);

name lookup will find the function template len, and template argument deduction will subsequently be applied with P as T[N] (as per [temp.deduct.call]/3) and A as int[3] for the single function parameter of len, which deduces T to int and N to 3 for the complete type deduction of the parameter type P; as per [temp.deduct.type]/1:

Template arguments can be deduced in several different contexts, but
in each case a type that is specified in terms of template parameters
(call it P) is compared with an actual type (call it A), and an
attempt is made to find template argument values (a type for a type
parameter, a value for a non-type parameter, or a template for a
template parameter) that will make P, after substitution of the
deduced values (call it the deduced A), compatible with A.

I.e., the non-type template parameter N is part of the type of the single function parameter (and so is the type template parameter T).

Deducing Non-Type Template Argument Unsigned Int / size_t

It is possible to deduce a non-type template argument from function arguments, but not in the way you want. It can only be deduced from the type of the function argument, not from the value.

For example:

template <unsigned int S>
void getsize(int (*s)[S]) {
std::cout << "pointer value: " << (void*)s << std::endl;
std::cout << "deduced size: " << S << std::endl;
}

getsize(static_cast<int (*)[4]>(0));

size_t and unsigned int does not match in a template function's parameter list


#include <cstddef>
template <class T>
struct istack
{
void push_back(T& value);
std::size_t size() const;
};

int main()
{
typedef istack<size_t> IndexStack;
IndexStack a, stack;
stack.push_back(a.size());
}

This code produces an error

In function 'int main()':
13 no matching function for call to 'istack<unsigned int>::push_back(size_t)'
note 5 candidates are: void istack<T>::push_back(T&) [with T = unsigned int]

Note that it lists candidates. (I suspect you are not reading / posting the entire error message.)

The given candidate doesn't match the call, because the reference is non-const. A temporary (such as the result of a.size()) cannot be bound to a non-const reference.

push_back should be taking a const T& value



Related Topics



Leave a reply



Submit