Как называется этот шаблон? - PullRequest
0 голосов
/ 08 сентября 2011

Я написал несколько шаблонных классов как часть большого шаблонного класса. Один позволяет мне включать или исключать переменные-члены из класса. Другой позволяет мне получить либо переданный параметр класса шаблона, либо заполнитель, который вместо этого использует NOP.

Они позволяют классам использовать свои собственные параметры шаблона для включения или исключения членов данных через одно очень общее определение класса, а операции предоставляют интерфейс, который предотвращает проблемы несоответствия типов.

В этом примере кода показана моя реализация в использовании, так как я предполагаю, что ее будет легче распознать в действии (классы, относящиеся к шаблону, называются «призраками»).

typedef int field1type, field2type, field3type;

template <bool field1exists, bool field2exists, bool field3exists>
struct GhostShowcase
{
  typename Ghost<int, field1exists>::type intField;
  typename Ghost<float, field2exists>::type floatField;
  typename Ghost<char, field3exists>::type charField;
};

GhostShowcase<true,false,true> foo; // has int and char fields
                                    // but an unusable float field
GhostShowcase<true,true,true> bar; // has all fields usable

В примерах ниже показано, как использовать операторы с типами, полученными из классов-призраков. Функция тестирования printAll() использует ghostStaticOperator() для вызова статических функций в классе, производном от GhostStaticOperation. Этот класс является либо классом, который был передан в качестве параметра шаблона в GhostStaticOperation, либо автоматически сгенерированным классом, который имеет статическую функцию с той же сигнатурой, но ничего не делает. Выбранный класс основан на параметре логического шаблона exists. в main() сделаны два звонка; первый передает параметр шаблона true, а второй - false.

В этих примерах показан компилируемый источник (в g ++ 4.5.2 с установленным -std = c ++ 0x). Этот файл может быть назван как угодно.

#include "ghost.h"
#include <iostream>
#include <functional>

using namespace Aryana;
using namespace std;

struct PrintingOperator : public std::unary_function<int, void>
{
  static inline void operation(int toPrint)
  {cout << toPrint;}
};

struct IncrementOperator : public std::unary_function<int&, void>
{
  static inline void operation(int& toIncrement)
  {++toIncrement;}
};

template <bool exists>
void printAll()
{
  typedef GhostStaticOperator<PrintingOperator, exists> printClass;
  typedef GhostStaticOperator<IncrementOperator, exists> incrClass;

  typename Ghost<int, exists>::type ghostObject;
  cout << "using ghost printer: ";
  ghostStaticOperation<printClass>(ghostObject);
  cout << "\nusing ghost incrementor...\n";
  ghostStaticOperation<incrClass>(ghostObject);
  cout << "using ghost printer: ";
  ghostStaticOperation<printClass>(ghostObject);
  cout << "\nfinished\n";
}

int main(int, char**)
{
  cout << "ghost operation with exists=true:\n";
  printAll<true>();
  cout << "ghost operation with exists=false:\n";
  printAll<false>();
}

Этот образец должен называться "ghost.h" и помещаться в тот же каталог, что и предыдущий файл.

typedef char ghost_null_argument[0];
typedef void ghost_null_return;

template <class S, bool exists>
class Ghost;

template <class S, bool exists>
class GhostOperator;

template <class S, bool exists>
class GhostStaticOperator;

template <class S>
class Ghost<S, false>
{
  Ghost(); // private constructor to prevent instantiation
 public:
  typedef ghost_null_argument type;
  typedef S original_type;
};

template <class S>
class Ghost<S, true>
{
  Ghost(); // private constructor to prevent instantiation
 public:
  typedef S type;
  typedef S original_type;
};

template <class S, bool exists>
class GhostOperator;

template <class S>
class GhostStaticOperator<S, false>
{
  GhostStaticOperator(); // private constructor to prevent instantiation
 public:
  typedef ghost_null_return result_type;
  typedef ghost_null_argument argument_type;
  struct operator_type
  {
    inline static result_type operation(argument_type){};
  };
};

template <class S>
class GhostStaticOperator<S, true>
{
  GhostStaticOperator(); // private constructor to prevent instantiation
 public:
  typedef S operator_type;
  typedef typename operator_type::result_type result_type;
  typedef typename operator_type::argument_type argument_type;
};

// must define argument_type and result_type in the operator class
// result_type will be ghost_null_argument if the class is ghosting
template <class S>
inline
typename S::result_type ghostStaticOperation(typename S::argument_type argument)
{
  return S::operator_type::operation(argument);
}

1 Ответ

1 голос
/ 09 сентября 2011

Я вполне уверен, что это шаблон "ошибка". char[0] не является допустимым типом члена.

Если серьезно, обычно мы используем SFINAE для прямой проверки членов, которые могут существовать или не существовать. Это позволяет избежать всего шаблона Ghost<T, bool>.

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