Не уверен, что понимаю, чего именно вы хотите, но ... я полагаю, вы можете использовать рекурсию и тип тега (скажем, std::integral_constant<std::size_t, N>
, где N
- аргумент шаблона Field
), чтобы различать методы получения и установкина разных уровнях.
Я имею в виду ... учитывая следующее Field
template <typename T, std::size_t N>
class Field : public Field<T, N-1u>
{
private:
std::string name;
T value;
public:
using Field<T, N-1u>::setField;
using Field<T, N-1u>::getFieldName;
using Field<T, N-1u>::getFieldValue;
using icnc = std::integral_constant<std::size_t, N> const;
virtual void setField (icnc &, std::string const & n0, T const & v0)
{
name = n0;
value = v0;
}
virtual std::string const & getFieldName (icnc &) const
{ return name; }
virtual T const & getFieldValue (icnc &) const
{ return value; }
};
и наземную специализацию Field<0>
, которые определяют поддельные методы
template <typename T>
class Field<T, 0u>
{
public:
// fake ground functions
virtual void setField () { };
virtual void getFieldName () { };
virtual void getFieldValue () { };
};
определяя Form
следующим образом
class Form : public Field<int, 10u>
{ };
у вас есть 10 виртуальных сеттеров и 20 (10 для имен и 10 для значений) виртуальных геттеров.
Ниже приведен полный рабочий пример
#include <string>
#include <iostream>
#include <type_traits>
template <typename T, std::size_t N>
class Field : public Field<T, N-1u>
{
private:
std::string name;
T value;
public:
using Field<T, N-1u>::setField;
using Field<T, N-1u>::getFieldName;
using Field<T, N-1u>::getFieldValue;
using icnc = std::integral_constant<std::size_t, N> const;
virtual void setField (icnc &, std::string const & n0, T const & v0)
{
name = n0;
value = v0;
}
virtual std::string const & getFieldName (icnc &) const
{ return name; }
virtual T const & getFieldValue (icnc &) const
{ return value; }
};
template <typename T>
class Field<T, 0u>
{
public:
// fake ground functions
virtual void setField () { };
virtual void getFieldName () { };
virtual void getFieldValue () { };
};
class Form : public Field<int, 3u>
{
// Form inherit three different setField, three different getFieldName
// and three different getFieldValie methods
};
template <std::size_t N>
using tag = std::integral_constant<std::size_t, N> const;
int main ()
{
Form f;
f.setField(tag<1u>{}, "field 1", 111);
f.setField(tag<2u>{}, "field 2", 222);
f.setField(tag<3u>{}, "field 3", 333);
std::cout << f.getFieldName(tag<1u>{}) << ", "
<< f.getFieldValue(tag<1u>{}) << std::endl;
std::cout << f.getFieldName(tag<2u>{}) << ", "
<< f.getFieldValue(tag<2u>{}) << std::endl;
std::cout << f.getFieldName(tag<3u>{}) << ", "
<< f.getFieldValue(tag<3u>{}) << std::endl;
}
Еще немного поработав внутри Form
, добавив установщик шаблонов и пару получателей шаблонов
class Form : public Field<int, 3u>
{
public:
using Field<int, 3u>::setField;
using Field<int, 3u>::getFieldName;
using Field<int, 3u>::getFieldValue;
template <std::size_t N>
using tag = std::integral_constant<std::size_t, N> const;
template <std::size_t N>
void setField (std::string const & n0, int v0)
{ setField(tag<N>{}, n0, v0); }
template <std::size_t N>
std::string const & getFieldName () const
{ return getFieldName(tag<N>{}); }
template <std::size_t N>
int const & getFieldValue () const
{ return getFieldValue(tag<N>{}); }
};
, вы можете упростить использование индекса тега
Form f;
f.setField<1u>("field 1", 111);
f.setField<2u>("field 2", 222);
f.setField<3u>("field 3", 333);
std::cout << f.getFieldName<1u>() << ", " << f.getFieldValue<1u>()
<< std::endl;
std::cout << f.getFieldName<2u>() << ", " << f.getFieldValue<2u>()
<< std::endl;
std::cout << f.getFieldName<3u>() << ", " << f.getFieldValue<3u>()
<< std::endl;