Специализация шаблонов на C ++ AMP с ограниченными лямбдами

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

// helper classes ========================================
template <typename R, typename... A>
class lambda_traits_evaluation {
public:
  typedef R r_type;
  enum { n_args = sizeof...(A) };
  // ...
};

template <typename R, typename... A>
class lambda_traits_helper
  : public lambda_traits_evaluation<R,A...>{};

template <typename R, typename F, typename... A>
class lambda_traits_helper<R (F::*)(A...) const>
  : public lambda_traits_evaluation<R,A...>{};

// use class      ========================================
template <typename F>
class lambda_traits {
  typedef typename lambda_traits_helper<decltype(&F::operator())> helper_impl;
  // ...
}

Затем я могу использовать это с lambda_traits<decltype(myLambda)>, но на этом мое самодовольное кодирование заканчивается, потому что, если моя лямбда ограничена для gpu, т.е.

auto myLambda = [](int) restrict(amp) -> void {};

так как явно не подобрана специализация шаблона. Однако добавление новой специализации

template <typename R, typename F, typename... A>
class lambda_traits_helper<R (F::*)(A...) const restrict(amp)>
  : public lambda_traits_evaluation<R,A...> {};

все еще не решает проблему, поскольку я обнаруживаю, что компилятор лает

error C3939: 'abstract declarator' : pointer to member functions, function
             pointers, references to functions with 'amp' restriction
             specifier are not allowed

есть ли другой способ опросить типы в лямбда-выражениях или способ снять ограничение с лямбда-типа?


person geoff3jones    schedule 19.12.2013    source источник


Ответы (1)


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

См. Следующий контрольный образец:

#include <type_traits>

template <typename R, typename F, typename... A>
auto get_R(R (F::*)(A...) const) -> R
{}

template <typename L>
struct lambda_traits
{
    using ret_type = decltype(get_R(&L::operator()));
};

int main()
{
    auto lambda_1 = [](int) restrict(cpu,amp) -> void {};
    auto lambda_2 = [](int) restrict(cpu,amp) -> int { return 0; };

    // Test:
    static_assert(std::is_same<lambda_traits<decltype(lambda_1)>::ret_type, void>::value, "Failed 1.");
    static_assert(std::is_same<lambda_traits<decltype(lambda_2)>::ret_type, int>::value, "Failed 2.");
}

Надеюсь, это поможет!

person Lukasz Mendakiewicz    schedule 20.01.2014
comment
Ммм аккуратно, это действительно жизнеспособный обходной путь. Я волновался, что не смогу использовать это для специализации шаблонных restrict(amp) функций, так как ожидал, что это приведет к потере части restrict(cpu). Как ни странно, ограничение процессора, кажется, цепляется за определение лямбда (хотя оно не вызывается) даже внутри ограниченной amp области. Я не уверен, что это ошибка реализации или что-то в этом роде, но она кажется немного сломанной ... В любом случае, спасибо, что заметили ее, и я не могу думать о каких-либо серьезных недостатках, требующих дополнительного cpu ограничения на лямбда. - person geoff3jones; 22.01.2014
comment
Да, ограничения (неформально) не снимаются при пересечении границы ограничения. В противном случае вы не сможете вызвать parallel_for_each с лямбда-выражением, ограниченным усилителем, из контекста, ограниченного процессором. - person Lukasz Mendakiewicz; 23.01.2014
comment
Ах, конечно, это хороший момент, я думаю, я запутался, проводя параллели с перегрузкой функций-членов на restric. Приветствую за помощь и идеи! - person geoff3jones; 23.01.2014