如何将第三方库模板类实例传入自定义类构造函数?
Hey there! Let's work through how to pass an instance of that third-party template class into your custom library class. I’ve got a few practical approaches that should fit different scenarios, depending on what you need:
1. Make Your Custom Class a Template Too
This is the most straightforward approach if you don’t mind your custom class being templated. It lets you directly accept the third-party template instance while preserving full type information.
Here’s a code example to illustrate:
// Third-party template class (example structure) template <typename T> class ThirdPartyTemplate { public: void doSomething(T value) { // Third-party implementation here } }; // Your custom class, now templated to match the third-party class template <typename T> class MyCustomClass { private: ThirdPartyTemplate<T>& tp_instance; // Use reference if you manage the instance's lifetime // Or use a pointer: ThirdPartyTemplate<T>* tp_instance; public: // Constructor takes a reference to the third-party instance MyCustomClass(ThirdPartyTemplate<T>& instance) : tp_instance(instance) {} void useThirdPartyFeature() { // Call methods on the third-party instance directly tp_instance.doSomething(42); } }; // Usage example int main() { ThirdPartyTemplate<int> tp_int_instance; MyCustomClass<int> my_class(tp_int_instance); my_class.useThirdPartyFeature(); return 0; }
Pros: No runtime overhead, full access to the third-party class’s methods, and minimal code changes.
Cons: Your custom class will generate separate instantiations for each T you use, which could increase compile time and binary size if you have many different types.
2. Use Type Erasure for Flexibility
If you want your custom class to work with any instantiation of the third-party template (without being templated itself), type erasure is a great option. This involves wrapping the third-party instance in an adapter that implements a common interface.
Check out this implementation:
#include <memory> // Define an abstract interface with the methods you need from the third-party class class ThirdPartyInterface { public: virtual ~ThirdPartyInterface() = default; virtual void performGenericAction() = 0; // Adjust to match your required methods }; // Template adapter that wraps the third-party instance and implements the interface template <typename T> class ThirdPartyAdapter : public ThirdPartyInterface { private: ThirdPartyTemplate<T>& tp_instance; public: ThirdPartyAdapter(ThirdPartyTemplate<T>& instance) : tp_instance(instance) {} void performGenericAction() override { // Map the interface method to the third-party class's method tp_instance.doSomething(42); } }; // Your custom class, now dependent only on the abstract interface class MyCustomClass { private: std::unique_ptr<ThirdPartyInterface> interface_ptr; public: // Template constructor to accept any third-party template instance template <typename T> MyCustomClass(ThirdPartyTemplate<T>& instance) { interface_ptr = std::make_unique<ThirdPartyAdapter<T>>(instance); } void useThirdParty() { interface_ptr->performGenericAction(); } }; // Usage example int main() { ThirdPartyTemplate<int> tp_int_instance; MyCustomClass my_class1(tp_int_instance); my_class1.useThirdParty(); ThirdPartyTemplate<std::string> tp_str_instance; MyCustomClass my_class2(tp_str_instance); my_class2.useThirdParty(); return 0; }
Pros: Your custom class stays non-templated, works with any instantiation of the third-party template, and keeps your code decoupled from the third-party implementation.
Cons: Small runtime overhead from virtual function calls, and you can only call methods defined in the abstract interface (you’ll need to extend the interface if you need more functionality).
3. Target Specific Template Instantiations
If you only need to support a fixed set of third-party template instantiations (e.g., ThirdPartyTemplate<int>, ThirdPartyTemplate<std::string>), you can use overloaded constructors or std::variant to handle them directly.
Here’s how to do it with std::variant:
#include <variant> // Third-party template class template <typename T> class ThirdPartyTemplate { public: void doSomething(T value) { /* ... */ } }; // Your custom class class MyCustomClass { private: std::variant<ThirdPartyTemplate<int>&, ThirdPartyTemplate<std::string>&> tp_variant; public: // Overloaded constructors for each supported type MyCustomClass(ThirdPartyTemplate<int>& instance) : tp_variant(instance) {} MyCustomClass(ThirdPartyTemplate<std::string>& instance) : tp_variant(instance) {} void useThirdParty() { // Use std::visit to handle each type case std::visit([](auto& instance) { instance.doSomething(42); // Works if all supported types have this method }, tp_variant); } };
Pros: No runtime overhead from virtual functions, type-safe, and your custom class remains non-templated.
Cons: Inflexible—you’ll need to modify the class every time you want to support a new template instantiation.
Final Recommendation
- Go with approach 1 if you need full access to the third-party class and don’t mind your custom class being templated.
- Use approach 2 if you need maximum flexibility and want to decouple your code from the third-party template.
- Choose approach 3 if you only need to support a small, fixed set of third-party instantiations.
内容的提问来源于stack exchange,提问作者LeSinge

