Calculate non-default template arguments with metaprogramming?

I have a template class that takes 1 to 8 integer arguments. The valid range for each argument is 0..15. The default value of 16 for each argument allows me to detect unused arguments.

I would like to have the number of user-provided arguments available as a compile-time constant. I can do this with a helper template class and a lot of partial specialization.

My question is: can I clear it using a bit of recursive metaprogramming. I have work, but it seems like this can be improved syntactically.

The variadic templates and something else C ++ 0x, unfortunately, are not available to me.

#include <stdint.h> #include <iostream> template<uint8_t p0,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4,uint8_t p5,uint8_t p6,uint8_t p7> struct Counter { enum { COUNT=8 }; }; template<uint8_t p0,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4,uint8_t p5,uint8_t p6> struct Counter<p0,p1,p2,p3,p4,p5,p6,16> { enum { COUNT=7 }; }; template<uint8_t p0,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4,uint8_t p5> struct Counter<p0,p1,p2,p3,p4,p5,16,16> { enum { COUNT=6 }; }; template<uint8_t p0,uint8_t p1,uint8_t p2,uint8_t p3,uint8_t p4> struct Counter<p0,p1,p2,p3,p4,16,16,16> { enum { COUNT=5 }; }; template<uint8_t p0,uint8_t p1,uint8_t p2,uint8_t p3> struct Counter<p0,p1,p2,p3,16,16,16,16> { enum { COUNT=4 }; }; template<uint8_t p0,uint8_t p1,uint8_t p2> struct Counter<p0,p1,p2,16,16,16,16,16> { enum { COUNT=3 }; }; template<uint8_t p0,uint8_t p1> struct Counter<p0,p1,16,16,16,16,16,16> { enum { COUNT=2 }; }; template<uint8_t p0> struct Counter<p0,16,16,16,16,16,16,16> { enum { COUNT=1 }; }; template<uint8_t p0,uint8_t p1=16,uint8_t p2=16,uint8_t p3=16, uint8_t p4=16,uint8_t p5=16,uint8_t p6=16,uint8_t p7=16> struct MyClass { void printArgCount() { std::cout << Counter<p0,p1,p2,p3,p4,p5,p6,p7>::COUNT << std::endl; } }; main() { MyClass<4,7,8,12,15,1> foo; foo.printArgCount(); } 
+4
source share
3 answers

Why not just check out the first 16 that appears?

 template <uint8_t p0, ...> struct Counter { enum { COUNT = (p1 == 16 ? 1 : p2 == 16 ? 2 : p3 == 16 ? 3 : p4 == 16 ? 4 : p5 == 16 ? 5 : p6 == 16 ? 6 : p7 == 16 ? 7 : 8 ) }; }; 
+5
source

You can do this, but still not as pretty / nice as some other solutions that others can use with C ++ 11:

 template< uint8_t p0 = 16,uint8_t p1 = 16,uint8_t p2 = 16,uint8_t p3 = 16,uint8_t p4 = 16,uint8_t p5 = 16,uint8_t p6 = 16,uint8_t p7 = 16> struct Counter { enum { COUNT= int(p0!=16) + int(p1!=16) + int(p2!=16) + int(p3!=16) + int(p4!=16) + int(p5!=16) + int(p6!=16) + int(p7!=16) }; int count() const { return COUNT; } }; 
+2
source

You can set the counter recursively, something like this:

 template<typename> struct Counter; template<> struct Counter<> { static const int COUNT = 0;}; template<typename T, typename... Args> struct count<T, Args...> //partial specialization { static const int value = 1 + count<Args...>::COUNT;}; 
0
source

All Articles