Сводка
По некоторым причинам мой шаблон функции-члена, который вызывает лямбда-функцию, не может быть скомпилирован с ошибка C2275 ... недопустимое использование этого типа в качестве выражения , но когда функция перемещается как свободная функция, она правильно компилируется.
Подробности
Сначала у меня есть базовый класс, в котором хранятся function
экземпляры.в vector
.Только производные классы могут добавлять function
экземпляры к этому vector
, вызывая add_external
.Все function
экземпляры могут быть публично вызваны путем вызова invoke_externals
.Производный класс будет добавлять лямбда-выражения как function
экземпляров.Эти лямбды, в свою очередь, будут вызывать шаблон функции базового класса invoke_internal
с другой «внутренней» лямбдой.Параметр шаблона для invoke_internal
является типом исключения, который будет явно перехвачен при выполнении «внутренней» лямбды в invoke_internal
:
using namespace std;
class base
{
public:
void invoke_externals()
{
for (auto it = funcs_.begin(); it != funcs_.end(); ++it)
{
(*it)();
}
}
protected:
void add_external(function<void(void)> func)
{
funcs_.push_back(func);
}
template <typename T>
void invoke_internal(function<void(void)> func)
{
try
{
func();
}
catch (const T&){}
catch (...){}
}
vector<function<void(void)>> funcs_;
};
Тогда у меня есть две тривиальные свободные функции, которые выдают logic_error
иruntime_error
исключений.Эти функции должны использоваться во «внутренней» лямбде, которая вызывается в invoke_internal
:
void throws_logic_error()
{
throw logic_error("");
}
void throws_runtime_error()
{
throw runtime_error("");
}
В конструкторе класса derived
две лямбды добавляются с помощью add_external
.Каждую из этих лямбд называют invoke_internal
«внутренними» лямбдами.Первый вызов invoke_internal
явно поймает logic_error
, который throws_logic_error
сгенерирует.Второй вызов invoke_internal
явно поймает runtime_error
, который выбросит throws_runtime_error
.
class derived : public base
{
public:
derived()
{
add_external([this]()
{
invoke_internal<logic_error>([]()
{
throws_logic_error();
});
});
add_external([this]()
{
invoke_internal<runtime_error>([]()
{
throws_runtime_error();
});
});
}
};
И чтобы связать все это вместе, создается экземпляр derived
и вызывается invoke_externals
для вызова«внешние» лямбды добавлены в конструктор derived
.Эти «внешние» лямбды, в свою очередь, будут вызывать «внутренние» лямбды, и сгенерированные исключения будут явно перехвачены:
int wmain(int, wchar_t*[])
{
derived().invoke_externals();
return 0;
}
Проблема
Однако вышеприведенныйне компилируется:
error C2275: 'std::logic_error' : illegal use of this type as an expression
error C2275: 'std::runtime_error' : illegal use of this type as an expression
... выдается для вызовов invoke_internal
в конструкторе derived
.
Если я перемещаю invoke_internal
из base
исделать его свободной функцией, затем скомпилировать.
Вопрос
Почему я получаю ошибку C2275 ... незаконное использование этого типа в качестве выражения когда шаблон функции является base
членом?
Примечание: Перемещение функции-нарушителя из base
не является оптимальным, поскольку в моем сценарии реальной жизни функция фактически выполняетиспользовать состояние своего класса по-разному.