Во-первых, с точки зрения компилятора CrtpBase<D>::template Run<Args ...>
- это бессмысленная / неполная комбинация токенов. В C ++ такого синтаксиса выражений нет. Это выглядит как попытка сформировать указатель на член, но это требует явного применения &
operator
return std::bind(&CrtpBase<D>::template Run<Args ...>, base, std::forward<Args> (args) ...);
Во-вторых, этот актерский состав
static_cast<D&>(*this)
попытается отбросить постоянство. Это не разрешено в static_cast
.
В-третьих, ваш
std::bind(&CrtpBase<D>::template Run<Args ...>, base, std::forward<Args> (args) ...);
связывает подразумеваемый параметр this
с параметром функции base
. Это не сработает, поскольку base
будет уничтожено, как только выйдет VoidFunction
(или как только закончится вызывающее выражение) . Как правильно заметил @aschepler в комментариях, передавая base
в значение CrtpBase<D>
, нарезал исходный объект CrtpDerived<int&>
. Передайте его по ссылке, а затем используйте &base
в качестве аргумента для std::bind
.
В-четвертых, std::bind
не будет связываться «по ссылке» , и std::forward
не поможет вам в этом. Это означает, что a
внутри вашей лямбды fn
не будет связано с x
. Используйте std::ref
, чтобы обойти это ограничение.
#include <functional>
#include <utility>
template <typename D>
struct CrtpBase {
template <typename ... Args>
bool Run(Args&& ... args) const {
return static_cast<const D&>(*this).Impl(std::forward<Args>(args) ...);
}
};
template <typename ... Args>
struct CrtpDerived : public CrtpBase<CrtpDerived<Args ...>> {
CrtpDerived(std::function<bool(Args ...)> function) : runable(std::move(function)) {}
bool Impl(Args&& ... args) const {
return this->runable(std::forward<Args>(args) ...);
}
std::function<bool(Args ...)> runable;
};
template <typename D, typename ... Args>
std::function<bool()> VoidFunction(CrtpBase<D> &base, Args&& ... args) {
return std::bind(&CrtpBase<D>::template Run<Args ...>, &base, std::forward<Args>(args) ...);
}
int main(int argc, char** argv) {
std::function<bool(int&)> fn = [](int& a)->bool { a /= 2; return (a % 2) == 1; };
CrtpDerived<int&> derived(fn);
int x = 7;
auto voided = VoidFunction(derived, std::ref(x));
bool out = voided();
if ((x == 3) && (out == false)) {
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}
И последнее: я не понимаю, почему вы ожидаете, что в итоге ваш out
будет false
.