在Scott Meyers的Effective Modern C ++第18项中,有一个未完成的工厂函数,如下面的代码所示。我试图完成它,但是,如果派生类有构造函数采用不同的参数,这个代码明显的原因不会编译。这是使用可变参数模板函数编写工厂函数的正确方法,还是应该使用SFINAE或其他一些习惯用法?
http://coliru.stacked-crooked.com/a/48b30d4f97133b9f
#include <string>
#include <memory>
class Base {
public:
virtual ~Base() = default;
};
class Derived1 : public Base {
public:
Derived1(std::string s, int i) {}
};
class Derived2 : public Base {
public:
Derived2(std::string s, std::string s2) {}
};
enum class BaseType {
Derived1,
Derived2
};
template<typename... Ts>
std::unique_ptr<Base> makeBase(BaseType type, Ts&&... args) {
std::unique_ptr<Base> ptr;
if (type == BaseType::Derived1)
ptr.reset(new Derived1(std::forward<Ts>(args)...));
if (type == BaseType::Derived2)
ptr.reset(new Derived2(std::forward<Ts>(args)...));
return ptr;
}
int main() {
auto d1 = makeBase(BaseType::Derived1, "aa", 1);
}
错误:
main.cpp: In instantiation of 'std::unique_ptr<Base> makeBase(BaseType, Ts&& ...) [with Ts = {const char (&)[3], int}]':
main.cpp:35:53: required from here
main.cpp:30:19: error: no matching function for call to 'Derived2::Derived2(const char [3], int)'
ptr.reset(new Derived2(std::forward<Ts>(args)...));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:16:7: note: candidate: Derived2::Derived2(std::__cxx11::string, std::__cxx11::string)
Derived2(std::string s, std::string s2) {}
^~~~~~~~
main.cpp:16:7: note: no known conversion for argument 2 from 'int' to 'std::__cxx11::string {aka std::__cxx11::basic_string<char>}'
main.cpp:14:11: note: candidate: constexpr Derived2::Derived2(const Derived2&)
class Derived2 : public Base {
^~~~~~~~
main.cpp:14:11: note: candidate expects 1 argument, 2 provided
main.cpp:14:11: note: candidate: constexpr Derived2::Derived2(Derived2&&)
main.cpp:14:11: note: candidate expects 1 argument, 2 provided