首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将CTAD用于lambda?

如何将CTAD用于lambda?
EN

Stack Overflow用户
提问于 2020-08-31 23:04:58
回答 2查看 121关注 0票数 0

大家下午好。我实现了几个类:

代码语言:javascript
复制
// 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;
};

你可以这样使用它:

代码语言:javascript
复制
// 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标准中,您可以使用以下内容:

代码语言:javascript
复制
// 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):

代码语言:javascript
复制
// 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;
}

也许我在什么地方遗漏了标准信息,或者它可能无法实现。请告诉我。我将很高兴得到任何信息。

错误:

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

发布于 2020-08-31 23:15:44

如果您的lambda没有捕获任何内容,那么您可以在调用点将其衰减为函数指针:

代码语言:javascript
复制
const HolderDelegate holder ( + [] (const size_t index) -> std::string { return std::to_string(index); });
                           // ^ decay to FP

然后,您可以为HolderDelegate添加一个扣减指南

代码语言:javascript
复制
template <typename Result, typename ... Args>
HolderDelegate(Result (*)(Args...)) -> HolderDelegate<Result, Args...>;

这是一个demo

票数 1
EN

Stack Overflow用户

发布于 2020-08-31 23:26:35

这很复杂。

使用

代码语言:javascript
复制
    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构造函数

代码语言:javascript
复制
    const HolderDelegate holder ([] (const size_t index) -> std::string {     return std::to_string(index); });

您遇到了一种先有鸡还是先有蛋的问题,因为lambda可以转换为std::function,但不是std::function

因此std::function的类型无法推断,自动扣款指南也不起作用。

为了绕过这个问题,我看到了三种可能的解决方案。

第一个是你的工作方式

代码语言:javascript
复制
    const std::function<std::string(size_t)> delegateRaw = [] (const size_t index) -> std::string {     return std::to_string(index); };
    const HolderDelegate holder (delegateRaw);

第二个是明确的HolderDelegates类型,所以根本不需要演绎

代码语言:javascript
复制
    // .................VVVVVVVVVVVVVVVVVVVVVVVvvv
    const HolderDelegate<std::string, std::size_t> holder ([] (const size_t index) -> std::string {     return std::to_string(index); });

第三个是涉及std::function的扣费指南。

代码语言:javascript
复制
    // ..........................VVVVVVVVVVVVVV...........................................................................-V
    const HolderDelegate holder (std::function([] (const size_t index) -> std::string {     return std::to_string(index); }));
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63673322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档