Pig*_*pag 5 c++ templates overloading
我正在使用C++模板编写一个抽象工厂,并遇到了一个小障碍.即,泛型类T可以提供以下一种或多种方式来构造对象:
static T* T::create(int arg);
T(int arg);
T();
Run Code Online (Sandbox Code Playgroud)
我正在编写抽象工厂类,以便它可以按给定的顺序自动尝试这三种潜在的构造:
template <class T>
class Factory {
public:
T* create(int arg) {
return T::create(arg); // first preference
return new T(arg); // this if above does not exist
return new T; // this if above does not exist
// compiler error if none of the three is provided by class T
}
};
Run Code Online (Sandbox Code Playgroud)
如何使用C++模板实现此目的?谢谢.
沿着这条线的东西应该工作:
struct S { static auto create(int) { return new S; } };
struct T { T(int) {} };
struct U {};
template<int N> struct tag: tag<N-1> {};
template<> struct tag<0> {};
class Factory {
template<typename C>
auto create(tag<2>, int N) -> decltype(C::create(N)) {
return C::create(N);
}
template<typename C>
auto create(tag<1>, int N) -> decltype(new C{N}) {
return new C{N};
}
template<typename C>
auto create(tag<0>, ...) {
return new C{};
}
public:
template<typename C>
auto create(int N) {
return create<C>(tag<2>{}, N);
}
};
int main() {
Factory factory;
factory.create<S>(0);
factory.create<T>(0);
factory.create<U>(0);
}
Run Code Online (Sandbox Code Playgroud)
它基于sfinae和标签调度技术.
基本思想是create将工厂的功能转发给一组内部功能.这些函数会测试您正在查找的功能,因为它们存在tag并在测试失败时被丢弃.由于sfinae,只要其中一个成功,代码就会编译,一切都按预期工作.
这是C++ 17中的类似解决方案:
#include <type_traits>
#include <iostream>
#include <utility>
struct S { static auto create(int) { return new S; } };
struct T { T(int) {} };
struct U {};
template<typename C> constexpr auto has_create(int) -> decltype(C::create(std::declval<int>()), bool{}) { return true; }
template<typename C> constexpr auto has_create(char) { return false; }
struct Factory {
template<typename C>
auto create(int N) {
if constexpr(has_create<C>(0)) {
std::cout << "has create" << std::endl;
return C::create(N);
} else if constexpr(std::is_constructible_v<C, int>) {
std::cout << "has proper constructor" << std::endl;
return new C{N};
} else {
std::cout << "well, do it and shut up" << std::endl;
(void)N;
return C{};
}
}
};
int main() {
Factory factory;
factory.create<S>(0);
factory.create<T>(0);
factory.create<U>(0);
}
Run Code Online (Sandbox Code Playgroud)
感谢@StoryTeller和@ Jarod42在这个艰难的早晨提供帮助.
在wandbox上查看并运行它.