Вывод типа шаблона с помощью шаблона переменной для вызовов функций - PullRequest
0 голосов
/ 21 февраля 2019

Я использую VC ++ /std:c++latest и хочу определить RET-Type, Class-Type и типы аргументов функции-члена, передаваемой в качестве параметра шаблона в структуру.Я нашел способ сделать это:

template <auto MEMBER>
class C;
template <class RET, class T, class... ARGS, RET(T::*MEMBER)(ARGS...)>
class C<MEMBER>
{
public:
    template <class... ARGS2>
    RET operator()(ARGS2&&... args)
    {
        // place holder
        (reinterpret_cast<T*>(0)->*MEMBER)(std::forward<ARGS2>(args)...);
    }
};
struct A
{
    void f(int, int) {}
};
int main()
{
    C<&A::f> c; // error C2079: 'instance' uses undefined class 'C'
    c(5, 5);
}

Но это решение работает только с g ++.

Так что

  1. это ошибка в VC ++?
  2. Есть ли другой способ достичь того же?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Намек на @ max66 позволил мне понять, что мне не нужно выводить аргументы функции, где можно легко определить тип возвращаемого значения и тип класса.

template <auto MEMBER>
struct C
{
    template <class RET, class T, class... ARGS>
    static constexpr auto deduce_RET(RET (T::*member)(ARGS...)) -> RET;
    template <class RET, class T, class... ARGS>
    static constexpr auto deduce_T(RET (T::*member)(ARGS...)) -> T;
    using RET = decltype(deduce_RET(MEMBER));
    using T = decltype(deduce_T(MEMBER));
    template <class... ARGS>
    RET operator()(ARGS&&... args)
    {
        return (reinterpret_cast<T*>(0)->*MEMBER)(std::forward<ARGS>(args)...);
    }
};

Редактировать:исправлена ​​ошибка для Visual Studio 2019: https://developercommunity.visualstudio.com/content/problem/464355/error-c2079-instance-uses-undefined-class-c.html

0 голосов
/ 21 февраля 2019

Не ответ (извините), но длинный комментарий: если вы хотите совершенную пересылку, вам нужны универсальные ссылки в шаблоне функции / метода

Я имею в виду ... Я предлагаю переписать operator() следующим образомили что-то подобное (я также добавил идеальную пересылку для T объекта)

template <typename U, typename ... As>
RET operator()(U && u, As && ... args)
{
    (std::forward<U>(u).*MEMBER)(std::forward<As>(args)...);
}

Так что вы можете написать (по крайней мере, на g ++ и clang ++)

A  a;
C<&A::f> c;
c(a, 5, 5);
...