由于纯粹是表面的原因(即为了使C++API更类似于动态类型语言的同一个API(,我有几个类:
namespace O {
class A {
public:
void foo() {
std::cout << "foo" << std::endl;
}
};
class B {
public:
void bar() {
std::cout << "bar" << std::endl;
}
};
};
我想要另一个类X
,上面每个类都有一个返回现有实例的方法,即:
X x;
auto a = x.getObject<"A">();
a.foo();
auto b = x.getObject<"B">();
b.bar();
return 0;
不知道如何编写和专门化模板getObject
。。。我怀疑,与简单地使用方法A& getObjectA();
和B& getObjectB();
相比,它会过于复杂,并且在语义上几乎相同。。。所以也许它看起来像一个";你做错了"事情。
我试过这样的东西,但它有几个错误:
class X {
public:
template<const char *N, class T>
T& getObject();
private:
O::A a;
O::B b;
};
template<>
O::A& X::getObject<"A", O::A>() {
return a;
}
template<>
O::B& X::getObject<"B", O::B>() {
return b;
}
我希望这个问题足够引起大家的兴趣。
目标语言是任何语言,最好是C++11,以最大限度地提高兼容性,但如果能采用最新的C++标准,情况会有所改善,那就太好了。
我建议使用枚举而不是字符串。字符串可能会出现拼写错误,通常IDE可以帮助键入枚举,但不能帮助键入任意字符串。此外,字符串作为模板参数仅在C++20之后可用。那么返回对象的函数可以简单到:
enum type {A,B};
template <type T>
typename type_to_type<T>::type getObject() { return {}; }
其中type_to_type
是专门用于您想要映射的每种类型的特征:
template <type T> struct type_to_type;
template <> struct type_to_type<A> { using type = O::A; };
template <> struct type_to_type<B> { using type = O::B; };
完整示例:
#include <iostream>
namespace O {
class A {
public:
void foo() {
std::cout << "foo" << std::endl;
}
};
class B {
public:
void bar() {
std::cout << "bar" << std::endl;
}
};
};
enum type {A,B};
template <type T> struct type_to_type;
template <> struct type_to_type<A> { using type = O::A; };
template <> struct type_to_type<B> { using type = O::B; };
template <type T>
typename type_to_type<T>::type getObject() { return {}; }
int main() {
auto a = getObject<A>();
a.foo();
auto b = getObject<B>();
b.bar();
}
即使使用字符串作为参数,基本思想也是一样的。您需要提供参数和要使用的实际类型之间的映射。像type_to_type
这样的特质相应地专业化是实现这一点的简单方法。