เมื่อเร็ว ๆ นี้ฉันได้เขียนฟังก์ชั่นเทมเพลตเพื่อแก้ปัญหาการทำซ้ำรหัสบางอย่าง ดูเหมือนว่านี้:
template<class T, class R, class... Args>
R call_or_throw(const std::weak_ptr<T>& ptr, const std::string& error, R (T::*fun)(Args...), Args... args) {
if (auto sp = ptr.lock())
{
return std::invoke(fun, *sp, args...);
}
else
{
throw std::runtime_error(error.c_str());
}
}
int main() {
auto a = std::make_shared<A>();
call_or_throw(std::weak_ptr<A>(a), "err", &A::foo, 1);
}
รหัสนี้ทำงานได้อย่างสมบูรณ์แบบclass A
ซึ่งมีลักษณะเช่นนี้:
class A {
public:
void foo(int x) {
}
};
แต่ล้มเหลวในการรวบรวมสำหรับหนึ่งเช่นนี้:
class A {
public:
void foo(const int& x) {
}
};
เหตุใดจึงเป็นเช่นนั้น (โดยเหตุใดฉันจึงหมายถึงว่าทำไมจึงไม่สามารถอนุมานประเภท) และวิธี (หากเป็นไปได้ทั้งหมด) ฉันจะทำให้รหัสนี้ทำงานร่วมกับการอ้างอิงได้อย่างไร ตัวอย่างสด
Args&&...
และstd::forward
?