Подсчитывать нестандартные аргументы шаблона с помощью метапрограммирования?
У меня есть класс шаблона, который принимает от 1 до 8 целочисленных аргументов. Допустимый диапазон для каждого аргумента равен 0..15. Значение по умолчанию 16 для каждого аргумента позволяет мне обнаружить неиспользуемые аргументы.
Я хотел бы, чтобы число аргументов, предоставленных Пользователем, было доступно в качестве константы времени компиляции. Я могу сделать это с помощью шаблона вспомогательный класс и много частичной специализации.
Мой вопрос в том, Могу ли я очистить это с помощью рекурсивного метапрограммирования. То, что у меня есть работает но мне кажется, что его можно было бы улучшить синтаксически.Шаблоны с переменным числом аргументов и что-нибудь еще в C++0х не доступны для меня, к сожалению.
#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();
}
3 ответа:
Почему бы просто не проверить первый
16
, который появляется ?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 ) }; };
Вы могли бы сделать это, но это все еще не так красиво/приятно, как некоторые другие решения, которые другие могут дать, используя 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; } };