Deducing the size of an array when a template template parameter is used

75 views Asked by At

A very simple method to find the number of elements in a template array is shown in the following discussion:

How does this function template deduce the size of an array?

I wanted to emulate the same method to get the number of elements in my template template array:

//classA.h

#include <type_traits>
#include <cstddef>
#include <iostream>

using std::is_same;
using std::size_t;
using std::cout;
using std::endl;

template<typename T> class A;
template<typename T>
using array2As = A<T>[2];

template<template<typename T>class A, size_t N>
size_t cal_size(A<T>*&[N]){
 return N;
}

template<typename T>
class A{
  public:
  A(T);
  private:
  A()=delete;
  A(const A&)=delete; 
  A& operator=(const A&)=delete;
  T elem;
};

template<typename T>
A<T>::A(T elem){
  static_assert(is_same<T,int>::value || is_same<T,double>::value, "Compilation error: type must be int or double");
  this->elem = elem;
}


#include "classA.h"

int main (){
 
 array2As<int> a = {A(5),A(7)};
 auto sz = cal_size(a); 
 array2As<double> b = {A(1.2),A(6.3)};
 auto sz = cal_size(b); 

 return 0;
}

For the above code I get the following compiler error:

In file included from main.cpp:1:
classA.h:18:19: error: ‘T’ was not declared in this scope
   18 | size_t cal_size(A<T>*&[N]){
      |                   ^
compilation terminated due to -Wfatal-errors.

Why am I getting this error?

3

There are 3 answers

0
Jarod42 On BEST ANSWER

T in template <typename T> class A doesn't introduce T. It is unused. you have to introduce typename T.

It should be

template <template <typename> class A, typename T, size_t N>
size_t cal_size(const A<T>(&)[N]){
     return N;
}

Demo

0
Ted Lyngmo On

The template template parameter needs to be introducted in the template template parameter list:

template <template <typename> class A, class T, size_t N>
// no name needed   ^^^^^^^^           ^^^^^^^ this is needed
constexpr size_t cal_size(A<T>(&)[N]) {
    return N;
}
2
Jan Schultke On

The parameter names in a template template parameter are useless in your case. In the parameter:

template<typename T> class A

... typename T introduces the name T, but only in the scope of the pointy brackets. T is only visible inside template<...>, not outside of it. See also Is there any use for named parameters into template template parameters. It cannot be deduced from A<T> because the name doesn't exist in that scope.

As @Jarod42 has said, you could write

template <template <typename> class A, typename T, size_t N>

But this wouldn't have any advantage over using the function from the question you've linked. Note that C++17 has introduced std::size, which works exactly like the linked function:

std::size_t sz = std::size(a); 

Note: the A template template parameter, and the A class template aren't necessarily the same. They just share a name by coincidence.