Метод класса с числом аргументов, указанным целочисленным параметром шаблона - PullRequest
4 голосов
/ 15 июля 2010

Не был точно уверен, как сформулировать этот вопрос или что искать, поэтому, если это совпадает с другим вопросом, пожалуйста, закройте и перенаправьте на соответствующий вопрос.

Предположим,

template<typename Type, int Size> class vector
{
  Type data[Size];
}

Можно ли заменить конструктор, который принимает число аргументов Size в специализациях шаблонов, таких как

template<typename Type> class vector3<Type,3>
{
  Type data[3];
  public:
    vector3( Type, Type, Type );
}

, чем-нибудь в неспециализированном классе шаблонов?Как «конструктор varargs», который создает конструктор с числом аргументов Size типа Type?

Решение, включающее функции C ++ 0x, прекрасно.

Ответы [ 4 ]

6 голосов
/ 15 июля 2010

В C ++ 0x у вас наконец-то есть template typedef!

Отказ от ответственности: ничего не скомпилировано ...

Из статьи Википедии:

template< typename second>
using TypedefName = SomeType<OtherType, second, 5>;

, что в вашем случае принесло бы

template <class Type>
using vector3 = vector<Type, 3>;

Я не могу сказать вам, сколько я жаждал этого;)

Однако это не решает проблему параметров,Как уже упоминалось, вы можете попробовать и использовать шаблоны с переменными значениями здесь, однако я не уверен относительно их применения в этом случае.Обычно используется с рекурсивными методами, и вам нужно будет бросить static_assert в середине.

Отредактировано , чтобы учесть комментарии.

template <class Type, size_t Size>
class vector
{
public:
  template <class... Args>
  vector(Args... args): data({args...})
  {
    // Necessary only if you wish to ensure that the exact number of args
    // is passed, otherwise there could be less than requested
    BOOST_MPL_ASSERT_RELATION(sizeof...(Args), ==, Size);
  }

private:
  T data[Size];
};

Другая возможность, которая уже доступна, состоит в том, чтобы объединить генерацию препроцессора с boost::enable_if.

template <class Type, size_t Size>
class vector
{
public:
  vector(Type a0, typename boost::enable_if_c< Size == 1 >::type* = 0);
  vector(Type a0, Type a1, typename boost::enable_if_c< Size == 2 >::type* = 0);
  // ...
};

Использование Boost.Preprocessor для генерации делает это проще.

BOOST_PP_REPEAT(MAX_COUNT, CONSTRUCTOR_MACRO, ~);

// where MAX_COUNT is defined to the maximum size you wish
// and CONSTRUCTOR_MACRO actually generates the constructor

#define CONSTRUCTOR_MACRO(z, n, data)                              \
  vector(                                                          \
    BOOST_PP_ENUM_PARAMS(n, Type a),                               \
    typename boost::enable_if_c< Size == n >::type* = 0            \
  );

Реализация конструктораоставлено в качестве упражнения для читателя.Это еще один вызов BOOST_PP_REPEAT.

Как вы можете видеть, это скоро станет уродливым, так что вам будет лучше, если вы сможете использовать вариационную версию шаблона.

3 голосов
/ 16 июля 2010

Существует еще одно решение вашей проблемы: использование параметров шаблона переменной в списке инициализатора

template<typename T, unsigned int N>
struct vector {
    T data[N];

    template<typename... Args>
    vector(Args... args) : data({args...}) { }
};

Однако число аргументов должно быть меньше или равно N, а их типы - толькобыть конвертируемым в T.

2 голосов
/ 16 июля 2010

Сначала вы должны рассмотреть возможность использования std::array.Он не отвечает всем вашим требованиям, но достаточно близок, чтобы, если различия не имели значения, вы могли сэкономить много работы.Проблема в том, что эта дешевая версия будет иметь конструкцию, которая принимает как 2 аргумента, так и 3.

template< typename T>
using Vector3 = std::array<T,3>;

Vector3 v1{1,2,3};
Vector3 v2{1,2}; // it sounds like you want to disallow this case.

В противном случае вы можете создать собственный класс, который будет работать примерно так же, как std::array, за исключением более требовательного конструктора.

template<typename T, std::size_t SIZE>
class Vector
{
public:
   template< typename ... Args >
   Vector( Args ... args ) :
      data({args...})
   {
      static_assert( sizeof...(Args) == SIZE,
                     "Incorrect number of arguments passed to Vector constructor");
   }
   /* lots of extra code here to add std::array -like methods */
private:
   // could use std::array here as well.
   T data[3];
};

template< typename T >
using Vector3 = Vector<T,3>;

Vector3 v1(1,2,3);
Vector3 v2(1,2); // error at compile time.
2 голосов
/ 15 июля 2010

Можно ли заменить конструктор, который принимает размер числа аргументов в шаблонных специализациях, как этот

Не без тонны повторяющегося механического кода, и максимальный размер будет ограниченпо количеству раз вы повторяете себя.Пример: boost :: tuple (который может иметь ту функциональность, которая вам нужна).

В C ++ 0x это не будет проблемой благодаря variadicшаблоны .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...