gpt4 book ai didi

c++ - 简单的类 MPL 类型映射模板

转载 作者:太空宇宙 更新时间:2023-11-04 13:54:36 25 4
gpt4 key购买 nike

我正试图找到一种优雅的方式来实现类似非常简单的 boost::mpl 类型映射的东西。
在我的上下文中,使用 MPL 或任何其他 boost 库不是一个选项。此外,我真正需要的唯一操作是初始化和查找。存储编译时值也很好(如果我使用基于 boost 的解决方案,我可以使用 boost::fusion::set 来做到这一点)。
我知道如何用特征类做我想做的事,但我认为语法有点过于冗长并且还有一些其他小缺点,例如您不能在类声明中定义 traits 特化,而且,一般来说,它不会全部整齐地放在一个地方。

这是我想使用特征实现的目标:

// base class definitions
class Foo {};
class Bar {};
class Baz {};

// traits base
template<typename T>
struct MyTraits {};

// traits specializations
template<>
struct MyTraits<Foo> {
static constexpr const char* name = "foo";
typedef double type;
};
template<>
struct MyTraits<Bar> {
static constexpr const char* name = "bar";
typedef std::string type;
};

// generic worker function
template<typename T>
void doStuff(const T& arg) {
std::cout << "got a " << MyTraits<T>::name << " - size: " << sizeof(typename MyTraits<T>::type) << std::endl;
}

int main(int, char*[]) {
Foo foo;
Bar bar;
Baz baz;

doStuff(foo);
doStuff(bar);
// this fails, as expected:
//doStuff(baz);
}

下面是我希望能够使用的语法:

typedef TMapTemplate<
TMapEntry<Foo, double, "foo">,
TMapEntry<Bar, string, "bar">
> tTraitsMap;

// generic worker function
template<typename T>
void doStuff(const T& arg) {
std::cout << "got a " << at<tTraitsMap,T>::value<1>() << " - size: " << sizeof(at<tTraitsMap,T>::type<0>) << std::endl;
}

(这样的东西是理想的,但我真的很喜欢简单的一对一类型映射)

最佳答案

所以,我最终修补了一些或多或少能满足我的要求的东西。它无论如何都不完美,但确实符合我想要的简单版本:

模板:

struct NotFound {};

template <typename TK, typename TV>
struct TMapEntry {
};

template <typename... TEntries>
struct TMap {
};

template <typename TK, typename TV, typename... TEntries>
struct TMap<TMapEntry<TK, TV>, TEntries...> {
typedef TMap<TEntries...> tNext;
template<typename T>
struct HeadResolver {
static constexpr bool match = is_same<TK, T>::value;
};

template<typename T>
using at = typename conditional<HeadResolver<T>::match, TV, typename tNext::template at<T>>::type;
};

template<>
struct TMap<> {
template<typename T>
using at = NotFound;
};

用法:

class Foo {};
class Bar {};
class Baz {};

void test() {
typedef TMap<> tEmptyMap;
static_assert(is_same<tEmptyMap::at<Foo>, NotFound>::value, "found something in empty map");
static_assert(is_same<tEmptyMap::at<int>, NotFound>::value, "found something in empty map");

typedef TMap<
TMapEntry<Foo, int>,
TMapEntry<Bar, float>,
TMapEntry<void, string>
> tMap;
static_assert(is_same<tMap::at<Foo>, int>::value, "map mismatch");
static_assert(is_same<tMap::at<Bar>, float>::value, "map mismatch");
static_assert(is_same<tMap::at<void>, string>::value, "map mismatch");
static_assert(is_same<tMap::at<Baz>, NotFound>::value, "map mismatch");
}

我在做这件事的时候想到了几点:

  • 它不检查或保证 key 的唯一性。
  • 我可以完全删除 TMapEntry 模板,让每个“ map 节点”处理 2 种头部类型(键和值)。用法看起来像这样:typedef TMap<Foo, int, Bar, float, void, string> tMap; ,看起来更灵活,但可能会隐藏错误。
  • 可变参数模板和模板别名使这一切变得非常顺利,仅需 20 行左右的代码。

关于c++ - 简单的类 MPL 类型映射模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22060824/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com