【问题标题】:Pass on already deduced type as parameter type for a callback将已经推断的类型作为回调的参数类型传递
【发布时间】:2021-05-01 14:36:01
【问题描述】:

所以我正在尝试执行以下操作

int x = 123;
myFunction(x, [](auto y) {
    std::cout << y;
});

myFunction被定义为

template <typename T>
void myFunction(T val, void(*callback)(T)) {
    callback(val);
} 

当尝试编译代码时,clang 给了我错误could not match 'void (*)(T)' against '(lambda at ...)'。我发现这是因为您无法从 lambda 推断类型。

这实际上没关系,因为我真正想要的是callback 的参数类型是从myFunctionval 参数推导出来的类型。

所以我的问题简单地说是,是否有可能以某种方式排除callback 参数的推断,而只使用val 的推断类型?

【问题讨论】:

    标签: c++ templates type-deduction


    【解决方案1】:

    是否有可能以某种方式将回调参数排除在推导之外,而只使用推导的 val 类型?

    当然。

    如果你定义这样的东西

    template <typename T>
    struct self
     { using type = T; };
    

    你可以定义myFunction()如下

    template <typename T>
    void myFunction(T val, void(*callback)(typename self<T>::type)) {
        callback(val);
    } 
    

    现在T 是从val 推导出来的,用于callback

    从C++20开始,可以避开self定义,使用新引入的std::type_identity_t

    template <typename T>
    void myFunction(T val, void(*callback)(std::type_identity_t<T>)) {
        callback(val);
    } 
    

    【讨论】:

    • 我可能会使用std::type_identity_t&lt;void(T)&gt;* callback
    【解决方案2】:

    一个选项(也有几个)是将可调用项作为模板参数传递,并允许模板为您处理一些细节 - 例如:

    template <typename T, typename FUNCTOR>
    void myFunction(T val, FUNCTOR callback) {
        callback(val);
    }
    
    // Note: could be a const ref:
    //void myFunction(T val, const FUNCTOR &callback) {
    
    
    int main()
    {
    
        int some_int{1};
        myFunction(some_int, [](auto y){ std::cout << y << std::endl; });
    
        float some_float{1.1f};
        myFunction(some_float, [](auto y){ std::cout << y << std::endl; });
    
        return 0;
    }
    

    此处的完整示例(按照您的代码 - 但可以进一步整理):https://godbolt.org/z/qr7T5GPd6

    【讨论】:

    • 谢谢。这肯定会起作用,但问题是回调类型是未知的,因此 IDE IntelliSense 将不知道类型是什么,并且无法自动完成类型的成员等等。 @max66 建议使 IntelliSense 知道该类型。
    • @PeterBechP 是的,这很可能是真的! - 虽然我认为在最新的 vsode/msvs 中有一些模板智能感知(或即将到来)。我稍微喜欢这种方法,只是因为它非常简单,如果您更改传入的内容等,则不需要重构(至少在函数模板中)......我猜是:简单性+可维护性与智能感知:)跨度>
    • 仿函数方式允许捕获 lambda :-)(但预期的签名确实不可见 :-/,std::function 有开销)。
    猜你喜欢
    • 2021-06-04
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    • 2017-10-15
    • 1970-01-01
    • 2020-07-14
    相关资源
    最近更新 更多