gpt4 book ai didi

c++ - 从 lambda 继承是什么意思?

转载 作者:IT老高 更新时间:2023-10-28 12:13:52 24 4
gpt4 key购买 nike

发现这段代码看起来很有趣:

auto a = [](){};

class B : decltype(a)
{
};

我想知道它的作用。这有什么用吗?

最佳答案

好吧,该代码将编译,但问题是您将无法默认构造该类的任何对象1,因为 lambda 不可访问(除了复制/移动构造函数)lambda 保证的唯一构造函数type 是一个 默认 复制/移动构造函数。而且没有默认构造函数

[expr.prim.lambda/21]

The closure type associated with a lambda-expression has no default constructor and a deleted copy assignment operator. It has a defaulted copy constructor and a defaulted move constructor ([class.copy]). [ Note: These special member functions are implicitly defined as usual, and might therefore be defined as deleted. — end note ]

或来自 cppreference :

//ClosureType() = delete;                     //(until C++14)
ClosureType(const ClosureType& ) = default; //(since C++14)
ClosureType(ClosureType&& ) = default; //(since C++14)

无法访问 lambda 构造函数的历史可以追溯到其早期提案,发现 here

在第 3 节第二段中,我引用:

In this translation, __some_unique_name is a new name, not used elsewhere in the program in a way that would cause conflicts with its use as a closure type. This name, and the constructor for the class, do not need to be exposed to the user—the only features that the user can rely on in the closure type are a copy constructor (and a move constructor if that proposal is approved) and the function call operator. Closure types do not need default constructors, assignment operators, or any other means of access beyond function calls. It may be worthwhile for implementability to forbid creating derived classes from closure types. ...

如您所见,该提案甚至建议禁止从闭包类型创建派生类。


1 当然您可以使用 a 复制初始化基类为了初始化 B 类型的对象.见 this


现在,回答您的问题:

Can this be useful in any way?

不是您的确切形式。你的只能用实例 a 实例化。 .但是,如果你继承自一个通用的 Callable Class,比如 lambda 类型,我可以想到两种情况。

  1. 创建一个以给定继承顺序调用一组仿函数的仿函数:

    一个简化的例子:

    template<typename TFirst, typename... TRemaining>
    class FunctionSequence : public TFirst, FunctionSequence<TRemaining...>
    {
    public:
    FunctionSequence(TFirst first, TRemaining... remaining)
    : TFirst(first), FunctionSequence<TRemaining...>(remaining...)
    {}

    template<typename... Args>
    decltype(auto) operator () (Args&&... args){
    return FunctionSequence<TRemaining...>::operator()
    ( TFirst::operator()(std::forward<Arg>(args)...) );
    }
    };

    template<typename T>
    class FunctionSequence<T> : public T
    {
    public:
    FunctionSequence(T t) : T(t) {}

    using T::operator();
    };


    template<typename... T>
    auto make_functionSequence(T... t){
    return FunctionSequence<T...>(t...);
    }

    示例用法:

    int main(){

    //note: these lambda functions are bug ridden. Its just for simplicity here.
    //For correct version, see the one on coliru, read on.
    auto trimLeft = [](std::string& str) -> std::string& { str.erase(0, str.find_first_not_of(' ')); return str; };
    auto trimRight = [](std::string& str) -> std::string& { str.erase(str.find_last_not_of(' ')+1); return str; };
    auto capitalize = [](std::string& str) -> std::string& { for(auto& x : str) x = std::toupper(x); return str; };

    auto trimAndCapitalize = make_functionSequence(trimLeft, trimRight, capitalize);
    std::string str = " what a Hullabaloo ";

    std::cout << "Before TrimAndCapitalize: str = \"" << str << "\"\n";
    trimAndCapitalize(str);
    std::cout << "After TrimAndCapitalize: str = \"" << str << "\"\n";

    return 0;
    }

    输出

    Before TrimAndCapitalize: str = " what a Hullabaloo     "
    After TrimAndCapitalize: str = "WHAT A HULLABALOO"

    查看 Live on Coliru

  2. 用重载的 operator()(...) 创建一个 Functor , 重载了所有基类的 operator()(...) :

    • Nir Friedman 在他的 answer 中已经给出了一个很好的例子。对这个问题。
    • 我还起草了一个类似的简化示例,取自他的。看看 on Coliru
    • Jason Lucas 在他的 CppCon 2014 presentation "Polymorphism with Unions" 中也展示了它的实际应用。 .你可以找到 repo here ,源代码中的确切位置之一here (感谢 Cameron DaCamara)

另一个很酷的技巧:由于 make_functionSequence(...) 的结果类型是一个可调用的类。您可以在以后附加更多 lambda 或可调用它。

    //.... As previously seen

auto trimAndCapitalize = make_functionSequence(trimLeft, trimRight, capitalize);

auto replace = [](std::string& str) -> std::string& { str.replace(0, 4, "Whaaaaat"); return str; };

//Add more Functors/lambdas to the original trimAndCapitalize
auto replaced = make_functionSequence(trimAndCapitalize, replace /*, ... */);
replaced(str2);

关于c++ - 从 lambda 继承是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38024024/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com