如何解决如何将CTAD用于lambda?
大家下午好。我实现了两节课:
// 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
解决方法
如果您的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。
,这很复杂...
使用
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); }));
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。