大家下午好。我实现了几个类:
// CallingDelegate
template <typename Result, typename ... Args>
class CallingDelegate
{
using TypeDelegate = std::function<Result(Args...)>;
public:
CallingDelegate() = delete;
CallingDelegate(const std::shared_ptr<TypeDelegate>& boxDelegate) : m_boxDelegate(boxDelegate) {}
public:
Result operator()(Args... args) const
{
if (m_boxDelegate)
{
const auto& delegate = (*m_boxDelegate.get());
if (delegate)
{
return delegate(std::forward<Args>(args)...);
}
}
return {};
}
private:
const std::shared_ptr<TypeDelegate> m_boxDelegate;
};
// HolderDelegate
template <typename Result, typename ... Args>
class HolderDelegate
{
using TypeDelegate = std::function<Result(Args...)>;
public:
using TypeCalling = CallingDelegate<Result, Args...>;
public:
~HolderDelegate() { (*m_boxDelegate.get()) = nullptr; }
HolderDelegate() = delete;
HolderDelegate(const TypeDelegate& delegate) : m_boxDelegate(std::make_shared<TypeDelegate> (delegate)) {}
//
template<typename TypeCallback>
HolderDelegate(const TypeCallback& callback) : m_boxDelegate(std::make_shared<TypeDelegate> (TypeDelegate(callback))) {}
public: /// NON COPY
HolderDelegate(const HolderDelegate&) = delete;
HolderDelegate& operator=(const HolderDelegate& other) = delete;
public:
inline TypeCalling getCalling() const { return TypeCalling(m_boxDelegate); }
private:
const std::shared_ptr<TypeDelegate> m_boxDelegate;
};你可以这样使用它:
// Func
void runDelegate(const std::function<std::string(size_t)> delegate)
{
for (size_t i = 0; i < 3; ++i)
{
printf("index: %zu => text: %s\n", i, delegate(i).c_str());
}
}
// Main
int main()
{
std::function<std::string(size_t)> delegate;
{
const HolderDelegate<std::string, size_t> holder ([] (const size_t index) -> std::string { return std::to_string(index); });
delegate = holder.getCalling();
runDelegate(delegate);
}
runDelegate(delegate);
return 0;
}在17标准中,您可以使用以下内容:
// Main
int main()
{
std::function<std::string(size_t)> delegate;
{
const std::function<std::string(size_t)> delegateRaw = [] (const size_t index) -> std::string { return std::to_string(index); };
const HolderDelegate holder (delegateRaw);
delegate = holder.getCalling();
runDelegate(delegate);
}
runDelegate(delegate);
return 0;
}但您不能像这样使用它(使用lambda):
// Main
int main()
{
std::function<std::string(size_t)> delegate;
{
const HolderDelegate holder ([] (const size_t index) -> std::string { return std::to_string(index); });
delegate = holder.getCalling();
runDelegate(delegate);
}
runDelegate(delegate);
return 0;
}也许我在什么地方遗漏了标准信息,或者它可能无法实现。请告诉我。我将很高兴得到任何信息。
错误:
main.cpp: In function 'int main()':
main.cpp:65:104: error: class template argument deduction failed:
const HolderDelegate holder ([] (const size_t index) -> std::string { return std::to_string(index); });
^
main.cpp:65:104: error: no matching function for call to 'HolderDelegate(main()::<lambda(size_t)>)'
main.cpp:44:2: note: candidate: 'template<class Result, class ... Args> HolderDelegate(const HolderDelegate<Result, Args>&)-> HolderDelegate<Result, Args>'
HolderDelegate(const HolderDelegate&) = delete;
^~~~~~~~~~~~~~
main.cpp:44:2: note: template argument deduction/substitution failed:
main.cpp:65:104: note: 'main()::<lambda(size_t)>' is not derived from 'const HolderDelegate<Result, Args>'
const HolderDelegate holder ([] (const size_t index) -> std::string { return std::to_string(index); });
^
main.cpp:42:2: note: candidate: 'template<class Result, class ... Args, class TypeCallback> HolderDelegate(const TypeCallback&)-> HolderDelegate<Result, Args>'
HolderDelegate(const TypeCallback& callback) : m_boxDelegate(std::make_shared<TypeDelegate>(TypeDelegate(callback))) {}
^~~~~~~~~~~~~~
main.cpp:42:2: note: template argument deduction/substitution failed:
main.cpp:65:104: note: couldn't deduce template parameter 'Result'
const HolderDelegate holder ([] (const size_t index) -> std::string { return std::to_string(index); });
^
main.cpp:39:2: note: candidate: 'template<class Result, class ... Args> HolderDelegate(const TypeDelegate&)-> HolderDelegate<Result, Args>'
HolderDelegate(const TypeDelegate& delegate) : m_boxDelegate(std::make_shared<TypeDelegate>(delegate)) {}
^~~~~~~~~~~~~~
main.cpp:39:2: note: template argument deduction/substitution failed:
main.cpp:65:104: note: 'main()::<lambda(size_t)>' is not derived from 'const TypeDelegate'
const HolderDelegate holder ([] (const size_t index) -> std::string { return std::to_string(index); });
^
main.cpp:38:2: note: candidate: 'template<class Result, class ... Args> HolderDelegate()-> HolderDelegate<Result, Args>'
HolderDelegate() = delete;
^~~~~~~~~~~~~~
main.cpp:38:2: note: template argument deduction/substitution failed:
main.cpp:65:104: note: candidate expects 0 arguments, 1 provided
const HolderDelegate holder ([] (const size_t index) -> std::string { return std::to_string(index); });
^
main.cpp:31:7: note: candidate: 'template<class Result, class ... Args> HolderDelegate(HolderDelegate<Result, Args>)-> HolderDelegate<Result, Args>'
class HolderDelegate
^~~~~~~~~~~~~~
main.cpp:31:7: note: template argument deduction/substitution failed:
main.cpp:65:104: note: 'main()::<lambda(size_t)>' is not derived from 'HolderDelegate<Result, Args>'
const HolderDelegate holder ([] (const size_t index) -> std::string { return std::to_string(index); });
^
mingw32-make[1]: *** [Makefile.Debug:105: debug/main.o] Error 1发布于 2020-08-31 23:15:44
如果您的lambda没有捕获任何内容,那么您可以在调用点将其衰减为函数指针:
const HolderDelegate holder ( + [] (const size_t index) -> std::string { return std::to_string(index); });
// ^ decay to FP然后,您可以为HolderDelegate添加一个扣减指南
template <typename Result, typename ... Args>
HolderDelegate(Result (*)(Args...)) -> HolderDelegate<Result, Args...>;这是一个demo。
发布于 2020-08-31 23:26:35
这很复杂。
使用
const std::function<std::string(size_t)> delegateRaw = [] (const size_t index) -> std::string { return std::to_string(index); };
const HolderDelegate holder (delegateRaw);将一个std::function<std::string(std::size_t)>传递给HolederDelegate构造函数,该构造函数有一个等待std::function的构造函数。
因此,新的(C++17)自动扣除指南会将HolderDelegates检测为HolderDelegates<std::string, std::size_t>。
但是如果将lambda函数传递给HolderDelegates构造函数
const HolderDelegate holder ([] (const size_t index) -> std::string { return std::to_string(index); });您遇到了一种先有鸡还是先有蛋的问题,因为lambda可以转换为std::function,但不是std::function。
因此std::function的类型无法推断,自动扣款指南也不起作用。
为了绕过这个问题,我看到了三种可能的解决方案。
第一个是你的工作方式
const std::function<std::string(size_t)> delegateRaw = [] (const size_t index) -> std::string { return std::to_string(index); };
const HolderDelegate holder (delegateRaw);第二个是明确的HolderDelegates类型,所以根本不需要演绎
// .................VVVVVVVVVVVVVVVVVVVVVVVvvv
const HolderDelegate<std::string, std::size_t> holder ([] (const size_t index) -> std::string { return std::to_string(index); });第三个是涉及std::function的扣费指南。
// ..........................VVVVVVVVVVVVVV...........................................................................-V
const HolderDelegate holder (std::function([] (const size_t index) -> std::string { return std::to_string(index); }));https://stackoverflow.com/questions/63673322
复制相似问题