0

I have a tuple style variadic template data type. I want to get tuple_size type function that gets the number of template parameters. However, I'm having trouble getting the following to work.

template<typename... T>
struct A
{
};

template<typename T, typename ...S>
struct A<T, S...>
{
  T t;
  A<S...> s;
};


template<typename T>
size_t size_A()
{
  return 1;
}

template<typename T, typename... S>
size_t size_A()
{
  return 1 + size_A<S...>();
}


int main() {
  A<int,double,uint> a {2,3.5,10};
  constexpr size_t n = size_A<decltype(a)>();
  std::cout << n << std::endl;
}

I get the following error:

error: call of overloaded ‘size_A<A<int, double, unsigned int> >()’ is ambiguous
   constexpr size_t n = size_A<decltype(a)>();

note: candidate: ‘size_t size_A() [with T = A<int, double, unsigned int>; size_t = long unsigned int]’
 size_t size_A()
        ^~~~~~

note: candidate: ‘size_t size_A() [with T = A<int, double, unsigned int>; S = {}; size_t = long unsigned int]’
 size_t size_A()
        ^~~~~~

How do I make it distinguish between having parameter packs and not having them?

The following does work but I want to just use the type and not have to find an instance of the type. The actual problem will have the type and maybe no instance of the type.

template<typename T>
constexpr size_t size(const A<T>& t)
{
  return 1;
}

template<typename T, typename... S>
constexpr size_t size(const A<T,S...>& t)
{
  return 1 + size(t.s);
}

This differs from the varidic template functions where the instance of the type is given.

How do I make size_A work like tuple_size so that I can get the number of template parameters just by the type?

Mochan
  • 1,329
  • 1
  • 13
  • 27
  • 3
    Just use `sizeof...(S)` to get the number of arguments in the pack `S` – Justin Jul 22 '19 at 14:52
  • Thank you. But, ```template constexpr size_t size_A() { return sizeof...(S); }``` This didn't work. It just returns 1 when it should be 3. – Mochan Jul 22 '19 at 14:58
  • 1
    [possible Demo](https://ideone.com/eAYY69). – Jarod42 Jul 22 '19 at 15:21
  • @Mochan must be an error somewhere else in the code, I'm confident `sizeof...(S)` returns the number of variadic argument in `S`. – Guillaume Racicot Jul 22 '19 at 15:25
  • That you @Jarod42. That works great. I didn't think of using a `struct`. I was fixated on finding a way to `enable_if` with parameter packs. – Mochan Jul 22 '19 at 15:27
  • @GuillaumeRacicot The following function with an instance works but without an instance doesn't work. I don't know why. ``` template constexpr size_t size(const A& t) { return sizeof...(S); } ``` – Mochan Jul 22 '19 at 15:32
  • @GuillaumeRacicot https://ideone.com/DkmBJP Here is the code doing this. I don't know what my error is. – Mochan Jul 22 '19 at 15:39
  • 1
    @Mochan I copy pasted your code in compiler explorer. It still works: https://godbolt.org/z/cQTUXH – Guillaume Racicot Jul 22 '19 at 15:39
  • 1
    @Mochan I don't know what you expect your code do. Everything is correct. You are sending *only one* type to your `size_A` function. That type is `decltype(a)`. Try sending `int,double,uint` it will return `3`. – Guillaume Racicot Jul 22 '19 at 15:42
  • 1
    @Mochan you also implemented a working version above that returns `sizeof...(S)` correctly with the template arguments of `A` with your `size(a)` function. I really don't know what else do you need. – Guillaume Racicot Jul 22 '19 at 15:44
  • @GuillaumeRacicot I wanted the size without an instance of `A`. I will only have the type of `A`. @Jarod42 gave me the solution which I will use. – Mochan Jul 22 '19 at 15:50
  • 1
    @Mochan your solution with `size` in your ideone demo was superior. Jarod42 solution is much more slow to compile. – Guillaume Racicot Jul 22 '19 at 15:53
  • 1
    @Mochan this code avoid recusivity, is simpler and faster to compile: https://godbolt.org/z/cOxA7D – Guillaume Racicot Jul 22 '19 at 15:57
  • @GuillaumeRacicot Thank you. Works great! – Mochan Jul 22 '19 at 16:41

0 Answers0