我试图在调用分配函数时使用 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&&'
如果我显式地实现分配,则程序将起作用。然而这并不是我所期望的。我不知道还有其他扣除。那我该如何解决呢?
a.operator=<double>(log_helper(1.0));
a.operator=<double>(1.0);
T
在这里处于非推导上下文中,因此您始终必须指定它。如果从声明中删除 std::type_identity_t
,则可以从 T
推导出 log_helper(1.0)
,但仍然不能推导出 1.0
。