无法推断模板参数“T”

couldn't deduce template parameter 'T'

提问人:xujh 提问时间:9/4/2023 最后编辑:Marek Rxujh 更新时间:9/4/2023 访问量:82

问:

我正在尝试在调用分配函数时使用 source_location::current() 作为默认参数来制作记录器库。

#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;
    }

    // ratio_t(double ratio = 0) : ratio(ratio) {
    //     printf("%p: construct\n", this);
    // }

    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); // it works
    a = 1.0; // <- problem here
}

但是我收到此错误:

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&&'

https://godbolt.org/z/9hbzejaWW

如果我显式实现赋值,progmma 将起作用。然而,这不是我所期望的。我没有意识到可能有任何其他扣除。那么我该如何解决呢?

    a.operator=<double>(log_helper(1.0));
    a.operator=<double>(1.0);
C++ 模板 std

评论

0赞 Marek R 9/4/2023
模板推导类型只能直接发生,它必须完美匹配。如果您需要转换,则禁用扣款。您需要从 转换为 .doublelog_helper<double>
0赞 xujh 9/4/2023
@MarekR是的,我知道如果我显式转换为 .但是,为什么编译器在这里进行隐式对话呢?的构造不是用 声明的。doublelog_helper<double>log_helperexplicit
0赞 Caleth 9/4/2023
@xujh隐式转换是默认的。 将其修改为显式explicit
0赞 xujh 9/4/2023
@Caleth我的意思是,的构造函数是隐式的。所以我认为编译器会帮助我隐式转换为我调用时log_helperdoublelog_helper<double>ratio_t.operator=
0赞 Caleth 9/4/2023
@xujh但前提是它知道使用,它不能只是双倍。模板扣分在转换前完成log_helper<double>

答:

1赞 Caleth 9/4/2023 #1

T在这里处于非推导上下文中,因此您始终必须指定它。如果从声明中删除,则可以从 中推导出 ,但仍然不能。std::type_identity_tTlog_helper(1.0)1.0

在 coliru 上看到它

评论

0赞 xujh 9/4/2023
谢谢你的回答。但是,这不就是用于这种隐式转换吗?坦率地说,我不太擅长它的使用std::type_identity_t
2赞 Caleth 9/4/2023
@xujh no,用于引入非演绎上下文std::type_identity_t
0赞 xujh 9/4/2023
我对你的说法有点困惑。我实际上是在尝试使用来避免显式转换。我不明白为什么它在这里不起作用。std::type_identity_t
1赞 Marek R 9/4/2023
@xujh这不是关于掩盖,而是关于模板演绎。由于引入了依赖类型(其下方是:),因此它阻止了编译器推导类型,并强制开发人员显式指定该类型。std::type_identity_ttypename std::type_identity::type
0赞 Marek R 9/4/2023
放弃使用 godbolt.org/z/E9jThWrKh 使您的代码更好一些,但我认为不可能在这种赋值中实现行号。std::type_identity_t