是否有优雅的方式在多态lambda中写入类型别名

时间:2018-05-02 02:14:12

标签: c++ type-alias

请考虑以下代码:

#include <initializer_list>
#include <vector>

    auto cref_lambda = [] (const auto& il){
        using T= typename decltype(il)::value_type;   
    };

    auto cval_lambda = [] (const auto il){
        using T=typename decltype(il)::value_type;
    };

    int main(){
    std::initializer_list<int> il;
    cref_lambda(il);
    cval_lambda(il);
    }

cref_lambda无法编译,因为我们正在尝试:: into一个引用。

我知道解决方法(使用std::remove_reference_t或仅使用decltype(*il.begin());),但我想知道是否有更好的习惯用法。

1 个答案:

答案 0 :(得分:1)

解决手头问题的方法是将std::decay_t添加到decltype指令中。来自cppreference

  

将lvalue-to-rvalue,array-to-pointer和function-to-pointer隐式转换应用于类型T,删除cv-qualifiers,并将结果类型定义为成员typedef类型。

最重要的是,它作为不符合上述任何注释的类型的标识。因此可以安全地编写

using T = typename std::decay_t<decltype(il)>::value_type;   

获取不合格的value_type,与函数签名无关。

现在问题的另一部分,如何写这个更短。好吧,在你的例子的情况下,可以说,因为你的lambda没有捕获任何东西,它也可以被自由函数模板替换。

template < typename T >
void cref(std::initializer_list<T> const &il) {
    /* use T and il */
}

或者它是否适用于任何容器

template < typename U >
void cref(U const &il) {
    using T = typename U::value_type;
    /* use T and il */
}

第一种情况的明显优势是,您可以免费访问T = value_type“。另一个优点(在我看来)是如果您不小心使用非std::initializer_list<T>的内容调用此函数,您将获得更清晰的编译器错误。您可以通过添加static_assert来弥补lambda的这个缺点,但这会使您最初想要找到的“短缺”更加紧张。

最后,如果你真的喜欢写作函数的lambda风格,或者你必须捕捉一些东西并且不能使用自由函数方法,你可能要考虑使用 GCC扩展来模板lambdas:< / p>

auto cref_lambda = [] <typename U> (U const &il){
    using T = typename U::value_type;
};

这可能是你能得到的最短时间。