在 std::function 和 lambda 中使用自动说明符
Using auto specifier in std::function and lambdas
我有一个名为 Handler
的 class,它存储了一些 lambda。例如,我想要做的是有一个 std::vector
of std::function
来存储我的所有事件。我真的想不通为什么 lambda 不能像我预期的那样工作。
这是 handler.h
:
class Handler
{
public:
Handler();
~Handler();
void Register(const char* outcome, std::function<auto()> lambda);
void Trigger(const char* outcome);
private:
std::vector<int> identifier;
std::vector<char*> outcome;
std::vector<std::function<auto()>> func;
};
和handler.cpp
:
Handler::Handler()
{
//ctor stuff here
}
Handler::~Handler()
{
this->func.clear();
this->outcome.clear();
this->identifier.clear();
//...
}
void Handler::Register(const char* outcome, std::function<auto()> lambda)
{
static int identifier = 0;
identifier++;
this->outcome.push_back((char*)outcome);
this->identifier.push_back(identifier);
this->func.push_back(lambda);
//Sort outcome
}
void Handler::Trigger(const char * outcome)
{
int i;
for (i = 0; i < this->identifier.size(); i++)
{
if (!strcmp(outcome, this->outcome.at(i)))
break;
}
this->func[i]();
}
但是,如果我在 Handler::Register
中指定 lambda,它不会让我抛出 no suitable user-defined conversion from "lambda []void ()->void" to "std::function<auto()> exists
。在此示例中,我使用 void
return 类型,但其他类型也出错,我不明白为什么 std::function
中的模板无法推断出它,如果它正在发生。
Handler* events = new Handler();
events->Register("Up", [=]() -> void { //Error here!
//do stuff
//return something?
});
有没有其他方法可以做到这一点,比如不重载 Handler::Register
?
auto
不是类型,所以 std::function<auto()>
也不是类型。从您的使用方式来看,std::function<void()>
可能就是您想要的。
如评论中所述,您的代码还有其他问题,因此我会将 Handler
更改为此
class Handler
{
public:
Handler();
// default ~Handler is fine
void Register(std::string outcome, std::function<void()> lambda);
void Trigger(const std::string & outcome outcome) const;
void Trigger(std::size_t index) const;
private:
using Outcomes = std::map<std::string, std::function<void()>/*, custom string comparator ?*/>;
std::vector<Outcomes::iterator> identifier;
Outcomes outcomes;
};
void Handler::Register(std::string outcome, std::function<void()> func)
{
auto emplaced = outcomes.emplace(std::move(outcome), std::move(func));
identifier.push_back(emplaced.first);
}
void Handler::Trigger(const std::string & outcome) const
{
outcomes.at(outcome)();
}
void Handler::Trigger(std::size_t index) const
{
identifier[index]->second();
}
我有一个名为 Handler
的 class,它存储了一些 lambda。例如,我想要做的是有一个 std::vector
of std::function
来存储我的所有事件。我真的想不通为什么 lambda 不能像我预期的那样工作。
这是 handler.h
:
class Handler
{
public:
Handler();
~Handler();
void Register(const char* outcome, std::function<auto()> lambda);
void Trigger(const char* outcome);
private:
std::vector<int> identifier;
std::vector<char*> outcome;
std::vector<std::function<auto()>> func;
};
和handler.cpp
:
Handler::Handler()
{
//ctor stuff here
}
Handler::~Handler()
{
this->func.clear();
this->outcome.clear();
this->identifier.clear();
//...
}
void Handler::Register(const char* outcome, std::function<auto()> lambda)
{
static int identifier = 0;
identifier++;
this->outcome.push_back((char*)outcome);
this->identifier.push_back(identifier);
this->func.push_back(lambda);
//Sort outcome
}
void Handler::Trigger(const char * outcome)
{
int i;
for (i = 0; i < this->identifier.size(); i++)
{
if (!strcmp(outcome, this->outcome.at(i)))
break;
}
this->func[i]();
}
但是,如果我在 Handler::Register
中指定 lambda,它不会让我抛出 no suitable user-defined conversion from "lambda []void ()->void" to "std::function<auto()> exists
。在此示例中,我使用 void
return 类型,但其他类型也出错,我不明白为什么 std::function
中的模板无法推断出它,如果它正在发生。
Handler* events = new Handler();
events->Register("Up", [=]() -> void { //Error here!
//do stuff
//return something?
});
有没有其他方法可以做到这一点,比如不重载 Handler::Register
?
auto
不是类型,所以 std::function<auto()>
也不是类型。从您的使用方式来看,std::function<void()>
可能就是您想要的。
如评论中所述,您的代码还有其他问题,因此我会将 Handler
更改为此
class Handler
{
public:
Handler();
// default ~Handler is fine
void Register(std::string outcome, std::function<void()> lambda);
void Trigger(const std::string & outcome outcome) const;
void Trigger(std::size_t index) const;
private:
using Outcomes = std::map<std::string, std::function<void()>/*, custom string comparator ?*/>;
std::vector<Outcomes::iterator> identifier;
Outcomes outcomes;
};
void Handler::Register(std::string outcome, std::function<void()> func)
{
auto emplaced = outcomes.emplace(std::move(outcome), std::move(func));
identifier.push_back(emplaced.first);
}
void Handler::Trigger(const std::string & outcome) const
{
outcomes.at(outcome)();
}
void Handler::Trigger(std::size_t index) const
{
identifier[index]->second();
}