Ошибка сопоставления параметра класса шаблона VC2017

У меня есть функция шаблона С++, которая используется в VS2013 без каких-либо проблем. Но когда я обновляюсь до VS2017, компилятор VC жалуется, что не может сопоставить список аргументов. Кто-нибудь может помочь мне, как исправить код?

Упрощенный фрагмент кода, демонстрирующий проблему здесь:

#include "stdafx.h"
#include <functional>
#include <memory>

class FS
{
};

typedef std::shared_ptr<FS> FSPtr;

class FSM
{
public:
    FSM() : m_pFs(new FS()) {}

    template <typename CALLABLE, typename... ARGS>
    typename std::enable_if<std::is_same<bool, std::result_of_t<CALLABLE(ARGS&&...)>>::value, std::result_of_t<CALLABLE(ARGS&&...)>>::type
        All(CALLABLE fn, ARGS&&... args) const        // line 21
    {
        std::function<bool()> rFunc = std::bind(fn, m_pFs, args...);
        bool bSuccess = rFunc();
        return bSuccess;
    }
private:
    FSPtr m_pFs;
};

class SFF
{
public:
    SFF() : m_pFsm(new FSM()) {}
    bool VF(FSPtr pFs)
    {
        return nullptr != pFs;
    }
    bool Do()
    {
        return m_pFsm->All(std::bind(&SFF::VF, this, std::placeholders::_1));        // line 41
    }

    bool TF(FSPtr pFs, int n)
    {
        return nullptr != pFs && 0 != n;
    }
    bool Do1(int n)
    {
        return m_pFsm->All(std::bind(&SFF::TF, this, std::placeholders::_1, std::placeholders::_2), n);        // line 49
    }

private:
    std::shared_ptr<FSM> m_pFsm;
};


int _tmain(int argc, _TCHAR* argv[])
{
    SFF oSff;

    bool bOk1 = oSff.Do();
    bool bOk2 = oSff.Do1(4);
    int rc =  (bOk1 && bOk2) ? 0 : 1;

    return rc;
}

И ошибки компилятора VS2017 VC:

1>------ Build started: Project: ConsoleApplication1, Configuration: Debug Win32 ------
1>ConsoleApplication1.cpp
1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.11.25503\include\utility(486): error C2338: tuple index out of bounds
1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.11.25503\include\functional(887): note: see reference to class template instantiation 'std::tuple_element<0,std::tuple<>>' being compiled
1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.11.25503\include\tuple(793): note: see reference to function template instantiation 'const tuple_element<_Index,_Tuple>::type &&std::get(const std::tuple<_Rest...> &&) noexcept' being compiled
1>        with
1>        [
1>            _Tuple=std::tuple<_Rest...>
1>        ]
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(41): note: see reference to class template instantiation 'std::result_of<std::_Binder<std::_Unforced,bool (__thiscall SFF::* )(FSPtr),SFF *,const std::_Ph<1> &> (void)>' being compiled
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(21): note: while compiling class template member function 'std::enable_if<std::is_same<bool,result_of<_Ty>::type>::value,result_of<_Ty>::type>::type FSM::All(CALLABLE,ARGS &&...) const'
1>        with
1>        [
1>            _Ty=CALLABLE (ARGS &&...)
1>        ]
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(41): error C2672: 'FSM::All': no matching overloaded function found
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(41): error C2893: Failed to specialize function template 'std::enable_if<std::is_same<bool,result_of<_Ty>::type>::value,result_of<_Ty>::type>::type FSM::All(CALLABLE,ARGS &&...) const'
1>        with
1>        [
1>            _Ty=CALLABLE (ARGS &&...)
1>        ]
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(41): note: With the following template arguments:
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(41): note: 'CALLABLE=std::_Binder<std::_Unforced,bool (__thiscall SFF::* )(FSPtr),SFF *,const std::_Ph<1> &>'
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(41): note: 'ARGS = {}'
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(49): error C2672: 'FSM::All': no matching overloaded function found
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(49): error C2893: Failed to specialize function template 'std::enable_if<std::is_same<bool,result_of<_Ty>::type>::value,result_of<_Ty>::type>::type FSM::All(CALLABLE,ARGS &&...) const'
1>        with
1>        [
1>            _Ty=CALLABLE (ARGS &&...)
1>        ]
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(49): note: With the following template arguments:
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(49): note: 'CALLABLE=std::_Binder<std::_Unforced,bool (__thiscall SFF::* )(FSPtr,int),SFF *,const std::_Ph<1> &,const std::_Ph<2> &>'
1>c:\users\s.chan\source\repos\consoleapplication1\consoleapplication1\consoleapplication1.cpp(49): note: 'ARGS = {int &}'
1>Done building project "ConsoleApplication1.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Любая помощь горячо приветствуется.

Соответствует ли показанный вывод ошибки показанному коду? Пожалуйста, укажите те строки, которые соответствуют строкам 21, 41 и 49 consoleapplication1.cpp. Используйте // line 21 и т. д.

Yunnosch 10.04.2019 08:02

Показанная ошибка возникает при компиляции данного фрагмента кода с использованием VS2017.

simon 10.04.2019 08:32

И показанный фрагмент кода не имеет номеров строк. Пожалуйста, облегчите людям чтение вашего вопроса, указав соответствующие строки.

Yunnosch 10.04.2019 08:32

Обратите внимание, что это не работает и с другими компиляторами. Так что проблема в самом коде, а не в версии VS.

P.W 10.04.2019 08:36

Этот код можно собрать и запустить под VS2013. Я не пробовал другой компилятор.

simon 10.04.2019 08:38
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
101
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Причина, по которой ваш код не компилируется, заключается в следующем:

bool Do()
{
    return m_pFsm->All(std::bind(&SFF::VF, this, std::placeholders::_1));
}

Здесь вы используете функцию-оболочку All для вызова функции VF. Но: 1) Функция All должна получать аргументы функции:

template <typename CALLABLE, typename... ARGS>
    typename std::enable_if<std::is_same<bool, std::result_of_t<CALLABLE(ARGS&&...)>>::value, std::result_of_t<CALLABLE(ARGS&&...)>>::type
    All(CALLABLE fn, ARGS&&... args) const        // line 21
{
    std::function<bool()> rFunc = std::bind(fn, m_pFs, args...);
    bool bSuccess = rFunc();
    return bSuccess;
}

Args здесь должен стоять один аргумент типа FSPtr, см. подпись SFF::VF.

Итак, правильный код должен быть:

return m_pFsm->All(std::bind(&SFF::VF, this, std::placeholders::_1), somethingOfFSPtrType);
Ответ принят как подходящий

Очевидно, fn (CALLABLE) в FSM::All() должно называться fn(m_pFs, args...), а не fn(args...)

Итак, ваш SFINAE неверен:

  • std::result_of_t<CALLABLE(ARGS&&...)> отсутствует аргумент m_pFs:

  • std::result_of_t<CALLABLE(FSPtr, ARGS&&...)>

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

template <typename CALLABLE, typename... ARGS>
auto All(CALLABLE fn, ARGS&&... args)
    -> std::enable_if_t<std::is_same_v<bool, decltype(fn(std::declval<FSPtr>(), args...))>, bool>
{

Также обратите внимание, что std::bind возвращает лямбду. Создание std::function из этого будет неэффективным. Лучше просто использовать возвращаемый тип как есть:

    auto rFunc = std::bind(fn, m_pFs, args...); // no need to cast to std::function
    rFunc();

Другие вопросы по теме