Как уменьшить аргументы шаблона?

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

public void Example()
{
  if(myLogger.isLoggable(Level.INFO))
      myLogger.info("A String");
  if(myLogger.isLoggable(Level.FINE))
      myLogger.fine("A more complicated String");
  // +1 for each test and log message
}

Становится этим:

public void Example()
{
   _LogInfo();
   _LogFine();
   // +0 for each test and log message
}

private void _LogInfo()
{
   if(!myLogger.isLoggable(Level.INFO))
      return;

   // Do your complex argument calculations/evaluations only when needed.
}

private void _LogFine(){ /* Ditto ... */ }
7
задан Alexey Malistov 19 November 2009 в 10:02
поделиться

3 ответа

Я бы просто не стал хранить указатель элемента в качестве аргумента шаблона:

template<class T, class Foo>
struct X {
    X(T Foo::*p): p(p) {}
    void operator()(Foo & f) {
        (f.*p) = 12 * (f.*p);   // simple example. could be more complex `operator()`
    }
private:
    T Foo::*p;
};

template <class T, class Foo>
X<T, Foo> MakeX(T Foo::*p)
{
    return p;
}

Я не думаю, что с вашим подходом возможно вывести типы: вы не можете использовать указатель -to-member передается функции, в которой происходит вывод типа.

Изменить: Однако могут быть решения на основе макросов.

Например, вы можете создать класс для создания экземпляров X, например:

template <class T, class Foo>
struct XMaker
{
    template <T Foo::*p>
    X<T, Foo, p> make() { return X<T, Foo, p>(); }
};

Теперь вы можете создать функцию make ... для вывода T и Foo:

template <class T, class Foo>
XMaker<T, Foo> make_x_maker(T Foo::*)
{
    return XMaker<T, Foo>();
}

Что позволяет написать макрос вроде:

#define CREATE_X(member) make_x_maker(member).make<member>()

Использование:

std::for_each(cont.begin(), cont.end(), CREATE_X(&FF::r) );
8
ответ дан 7 December 2019 в 01:22
поделиться

У меня есть один вопрос: действительно ли вам нужно указать все эти аргументы?

struct XR
{
  template <class Foo>
  void operator()(Foo& foo) const { foo.r = 12 * foo.r; }
};

Это работает, нет необходимости в дополнительном методе make , он просто работает:

void testforx()
{
  std::vector<FF> cont(5);
  std::for_each(cont.begin(), cont.end(), XR()); 
}

Я предпочитаю не быть СЛИШКОМ универсальным при создании шаблонов.

Если вы вам нужен более сложный оператор operator () , вы всегда можете сделать тяжелую работу ВНУТРИ этого.

Также вы можете рассмотреть Boost.Bind ,

1
ответ дан 7 December 2019 в 01:22
поделиться

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

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

template<typename Func>
class X
{
public:
    explicit X(Func f = Func()) : f(f) {}

    template<class K>
    void operator()(K & k) const {
       f(k) = 12 * f(k);
    }
private:
    Func f;
};

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

1
ответ дан 7 December 2019 в 01:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: