免责声明:我不是 C++ 程序员,所以不要将此答案视为在 C++ 中执行此操作的正确方法。这只是一种非常脆弱的方法,而且可能大部分都是错误的。
//I've used char pointers below, because it's not possible to directly write string //literals in templates without doing some more complex stuff that isn't relevant here
//field1 and field2 are the names of the fields/keys
const char field2[] = "field2";
const char field1[] = "field1";
//foo and bar are the strings that determine what the
//type of the fields will be
const char foo[] = "foo";
const char bar[] = "bar";
//This represents a key and the determining string (foo/bar)
template <const char * name, const char * det>
struct Named {};
//What the type of the field will be if it maps to "foo"
struct ExampleType {
std::string msg;
};
//The end of a cons structure
struct End{};
//A cons-like structure, but for types
template <typename T, typename N>
struct Cons {
typedef T type;
typedef N Next;
};
//This'll be used to create new types
//While it doesn't return a type, per se, you can access the
//"created" type using "FromSpec<...>::type" (see below)
template <typename T>
struct FromSpec;
//This will handle any Named template where the determining string
//is not "foo", and gives void instead of ExampleType
template <const char * name, const char * det, typename rest>
struct FromSpec<Cons<Named<name, det>, rest>> {
//Kinda uses recursion to find the type for the rest
typedef Cons<void, typename FromSpec<rest>::type> type;
};
//This will handle cases when the string is "foo"
//The first type in the cons is ExampleType, along with the name
//of the field
template <const char * name, typename rest>
struct FromSpec<Cons<Named<name, foo>, rest>> {
typedef Cons<ExampleType, typename FromSpec<rest>::type> type;
};
//This deals with when you're at the end
template <>
struct FromSpec<End> {
typedef End type;
};
现在你可以像这样使用它了:
typedef Cons<Named<field1, foo>, Cons<Named<field2, bar>, End>> C;
//Notice the "::type"
typedef FromSpec<C>::type T;
T 等价于Cons<ExampleType, Cons<void, End>>
然后你可以像这样访问里面的类型:
typedef T::type E; //Equivalent to ExampleType
typedef T::type::Next N; //Equivalent to Cons<void, End>
typedef N::type v; //Equivalent to void
示例用法
int main() {
ExampleType et = { "This is way too complicated!" };
//You can kinda have values of type "void", unfortunately,
//but they're really just null
// v
N inner = { nullptr, new End() };
T obj = { &et, &inner };
Cons<ExampleType, Cons<void, End>> obj2 = obj;
std::cout << et.msg << std::endl;
}
打印“这太复杂了!”
Link to repl.it
如果我的答案有错误或可以改进,请随时编辑我的答案。我主要只是试图将the answer 由@Alec 翻译成C++。