You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++11中用decltype实现make_logger函数并适配代码?

问题:C++11环境下用decltype实现make_logger函数

先把我们手头的现有代码梳理清楚,方便后续分析:

基础加法函数

#include <iostream>
#include <functional>
#include <string>

using namespace std; // 为了C++11环境下代码简洁,避免重复写std::前缀

float add(float x, float y) { 
    cout << "\n in the add function \n"; 
    float res = x + y; 
    cout << "\n exiting the add function \n"; 
    return res; 
}

Logger类的前向声明与实现

// 前向声明
template <typename> struct Logger;

// 针对函数类型的特化实现
template<typename R, typename... Args> 
struct Logger<R(Args...)> { 
    function<R(Args...)> func; 
    string name; 

    // 构造函数
    Logger(const function<R(Args...)>& func, const string& name) 
        : func{func}, name{name} { } 

    // 重载函数调用运算符
    R operator()(Args... args) const { 
        cout << "\n Entering Into ... .......\n" << name << endl; 
        R result = func(args...); // 调用被包装的基础函数
        cout << "\n Exiting from ... \n" << name << endl; 
        return result; 
    } 
};

原make_logger函数与使用示例

// 原make_logger实现
template <typename R, typename... Args> 
auto make_logger(R (*func)(Args...), const string& name) { 
    return Logger<R(Args...)>{function<R(Args...)>(func), name}; 
}

// 使用示例
int main() {
    auto logger_add = make_logger(add, "**Adding Numbers**"); 
    auto result = logger_add(2.0f, 3.0f); // 注意C++11里浮点数字面量默认是double,用2.0f匹配float参数更严谨
    return 0;
}

核心问题解答

1. 原代码能在C++11环境运行吗?

可以,但需要注意两个关键细节:

  • 必须手动包含必要的头文件:<iostream>、<functional>、<string>,C++11不会自动引入这些标准库头文件
  • 调用logger_add时,建议传入float类型的字面量(比如2.0f),而非默认的double类型(2.0),虽然隐式转换也能运行,但显式匹配参数类型更符合C++11的类型严谨性要求

2. 如何用decltype实现make_logger?

原make_logger需要显式指定模板参数R和Args...,用decltype可以让编译器自动推导函数类型,实现更通用的包装逻辑。在C++11里,因为auto作为返回类型时需要尾置返回类型(trailing return type),具体写法如下:

// 基于decltype的make_logger实现(完全兼容C++11)
template <typename Func>
auto make_logger(Func func, const string& name) -> Logger<decltype(func)> {
    return Logger<decltype(func)>{function<decltype(func)>(func), name};
}

为什么这样可行?

  • 模板参数Func可以接受任意可调用对象:函数指针、lambda、std::function都能适配,比原版本的适用范围更广
  • decltype(func)会直接获取传入函数的原始类型,比如add的类型是float(float, float),正好匹配我们的Logger<R(Args...)>特化模板
  • 尾置返回类型-> Logger<decltype(func)>是C++11里auto作为返回类型时的必要写法,用来明确告诉编译器返回值的具体类型
  • 构造Logger时,function<decltype(func)>(func)把传入的可调用对象转换成对应的std::function实例,完美匹配Logger构造函数的参数要求

用这个版本的make_logger,原有的使用示例完全不需要修改就能正常运行,而且还能无缝包装其他类型的函数(比如int(int, int)类型的加法函数),不需要修改make_logger的代码。


内容的提问来源于stack exchange,提问作者rrai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:47:21