Универсальная оболочка C ++ - PullRequest
       10

Универсальная оболочка C ++

1 голос
/ 19 октября 2011

Я пытаюсь написать универсальную оболочку на C ++. Вот что я написал до сих пор:

//primary template 
template<typename T> 
class function
{
};
//partially specialized template

template<typename T, typename U, typename V> 
class wrapper<T(U,V)> 
{
private:
   //typedef pointer to function
   typedef T (*pfn)(U,V);
   pfn f;

public:

  wrapper(pfn func):f(func)
  {
  };

  T operator()(U a, V b)
  {
    return f(a,b);
  }
};

Который может быть создан с использованием, например:

wrapper<double(double, double)> someWrapper( &someFunction );

Мне было интересно, может ли кто-нибудь указать мне правильное направление с точки зрения того, как изменить шаблон оболочки, чтобы можно было создавать его экземпляры также следующими способами:

wrapper<double(double, double)> somewrapper( &someClass, &someClass::someFunction)
wrapper<double(someClass*, double)> somewrapper( &someClass::someFunction)

Буду признателен за любую помощь в этом.

Ответы [ 2 ]

2 голосов
/ 19 октября 2011

Вместо этого используйте std::function или реализацию Boost, если у вашего компилятора еще нет TR1. Тем не менее, это специализация, которую вы ищете указатель на функции-члены:

template<typename T, typename C, typename U, typename V> 
class wrapper<T (C::*)(U,V)> 
{
private:
   //typedef pointer to member-function
   typedef T (C::*pfn)(U,V);
   pfn f;

public:

  wrapper(pfn func):f(func)
  {
  };

  T operator()(C c, U a, V b)
  {
    return (c.*f)(a,b);
  }
};

и его экземпляр, подобный этому:

wrapper< double(someClass::*)(double, double) > somewrapper;

Первое создание, которое вы дали, не является невозможным, но для его работы требуется огромное количество стираемых типов, поскольку тип класса не может быть выведен из аргумента конструктора.

wrapper<double(double, double)> somewrapper( &someClass, &someClass::someFunction)

Второй можно заставить работать, немного изменив мой пример кода, предполагая, что вы хотите создать его экземпляр только с указателем на функции-члены.

wrapper<double(someClass*, double)> somewrapper( &someClass::someFunction)

Предполагая, что вы хотите, чтобы одно определение обертки могло использоваться как для свободных функций, так и для функций-членов с совместимыми аргументами, вам снова потребуется некоторое стирание типов, чтобы оно работало. Реализация Boost.Function фактически использует другую технику, чтобы избежать вызовов virtual.

2 голосов
/ 19 октября 2011

Если вы делаете это как упражнение по программированию и обучению, тогда это нормально, но существует много жизнеспособных альтернатив, которые существуют и тщательно проверены. Если вы используете C ++ 11, вы можете использовать std::function, в противном случае есть boost::function и boost::bind.

Теперь, предполагая, что это учебное упражнение, вам нужно будет создать версии вашей оболочки для каждого числа различных параметров и возвращаемых значений. Вам также нужно будет рассмотреть случаи, когда функция является членом класса, и вам может потребоваться рассмотреть также случай, когда вы имеете дело с классом Functor.

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

...