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

C++使用source_location时operator=模板参数推导失败求助

解决赋值运算符模板参数无法自动推导的问题

问题背景

开发日志库时,希望在调用赋值函数时自动将std::source_location::current()作为默认参数传递。现有代码中,显式指定模板参数调用赋值运算符可以正常运行,但直接使用a = 1.0这类简洁写法会报错,提示无法推导模板参数T。

原始代码

#include <iostream>
#include <source_location>
#include <type_traits>

template <class T>
struct log_helper { 
    log_helper(const T& o, std::source_location sl = std::source_location::current()) 
        : value(o), sl(sl) {}
    T value;
    std::source_location sl;
};

struct ratio_t {
    operator double() const {
        return ratio;
    }

    template<class T, class = typename std::enable_if_t<std::is_arithmetic_v<T>>>
    ratio_t& operator=(const log_helper<std::type_identity_t<T>>& o) {
        ratio = o.value;
        
        line = o.sl.line();
        func = o.sl.file_name();
        printf("file: %s line: %d\n", func.c_str(), line);

        return *this;
    }

    void clear() {
        ratio = 0.0f;
        line = 0;
        func.clear();
    }

    double get_ratio() const {
        return ratio;
    }

    uint32_t get_line() const {
        return line;
    }

    std::string get_func() const {
        return func;
    }
private:
    double ratio{0.0f};
    uint32_t line{0};

    std::string func;
};

int main() {
    ratio_t a;
    // a.operator=<double>(log_helper(1.0));
    // a.operator=<double>(1.0); // 可以正常运行
    a = 1.0; // <- 此处报错
}

错误信息

b.cpp: In function 'int main()':
b.cpp:61:9: error: no match for 'operator=' (operand types are 'ratio_t' and 'double')
   61 |     a = 1.0;
      |         ^~~
b.cpp:23:14: note: candidate: 'template<class T, class> ratio_t& ratio_t::operator=(const log_helper<typename std::type_identity<_Tp>::type>&)' 
   23 |     ratio_t& operator=(const log_helper<std::type_identity_t<T>>& o) {
      |              ^~~~~~~~
b.cpp:23:14: note:   template argument deduction/substitution failed:
b.cpp:61:9: note:   couldn't deduce template parameter 'T'
   61 |     a = 1.0;
      |         ^~~
b.cpp:13:8: note: candidate: 'ratio_t& ratio_t::operator=(const ratio_t&)'
   13 | struct ratio_t {
      |        ^~~~~~~
b.cpp:13:8: note:   no known conversion for argument 1 from 'double' to 'const ratio_t&'
b.cpp:13:8: note: candidate: 'ratio_t& ratio_t::operator=(ratio_t&&)'
b.cpp:13:8: note:   no known conversion for argument 1 from 'double' to 'ratio_t&&'

错误原因

模板参数推导过程中,编译器不会自动将double这类算术类型隐式转换为log_helper<double>来匹配赋值运算符的参数类型,因此无法推导模板参数T。只有当实参类型与函数参数类型完全匹配(或仅涉及内置转换)时,模板参数才能被自动推导。

解决方案

修改ratio_t的赋值运算符,让它直接接受算术类型T的参数,在函数内部构造log_helper<T>以自动获取当前的source_location。这样模板参数T可以直接从赋值右侧的实参推导出来,同时满足日志记录需求。

修改后的代码

#include <iostream>
#include <source_location>
#include <type_traits>

template <class T>
struct log_helper { 
    log_helper(const T& o, std::source_location sl = std::source_location::current()) 
        : value(o), sl(sl) {}
    T value;
    std::source_location sl;
};

struct ratio_t {
    operator double() const {
        return ratio;
    }

    // 修改后的赋值运算符:直接接受算术类型T
    template<class T, class = std::enable_if_t<std::is_arithmetic_v<T>>>
    ratio_t& operator=(const T& val) {
        log_helper<T> helper(val); // 自动获取当前source_location
        ratio = helper.value;
        
        line = helper.sl.line();
        func = helper.sl.file_name();
        printf("file: %s line: %d\n", func.c_str(), line);

        return *this;
    }

    void clear() {
        ratio = 0.0f;
        line = 0;
        func.clear();
    }

    double get_ratio() const {
        return ratio;
    }

    uint32_t get_line() const {
        return line;
    }

    std::string get_func() const {
        return func;
    }
private:
    double ratio{0.0f};
    uint32_t line{0};

    std::string func;
};

int main() {
    ratio_t a;
    a = 1.0; // 现在可以正常运行
    a = 42;  // 也支持整数类型
}

说明

  • 修改后的赋值运算符直接接收T类型参数,模板参数T能从右侧实参(如1.0、42)自动推导。
  • 在函数内部构造log_helper<T>时,会自动使用默认参数std::source_location::current()获取当前代码位置,完美实现日志记录需求。
  • 保留了std::enable_if_t<std::is_arithmetic_v<T>>的约束,确保只有算术类型能触发这个赋值运算符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 22:58:18