元编程:动态声明一个新的结构 [英] Meta programming: Declare a new struct on the fly

查看:81
本文介绍了元编程:动态声明一个新的结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以即时声明一个新类型(一个空的struct,或者没有实现的结构)?

Is it possible to declare a new type (an empty struct , or a struct without an implementation) on the fly?

例如

constexpr auto make_new_type() -> ???;

using A = decltype(make_new_type());
using B = decltype(make_new_type());
using C = decltype(make_new_type());

static_assert(!std::is_same<A, B>::value, "");
static_assert(!std::is_same<B, C>::value, "");
static_assert(!std::is_same<A, C>::value, "");

手动"解决方案是

template <class> struct Tag;

using A = Tag<struct TagA>;
using B = Tag<struct TagB>;
using C = Tag<struct TagC>;

甚至

struct A;
struct B;
struct C;

但是对于模板/meta来说,一些神奇的make_new_type()函数会很不错.

but for templating / meta some magic make_new_type() function would be nice.

现在状态元编程的格式不正确,这样的事情还能实现吗?

Can something like that be possible now that stateful metaprogramming is ill-formed?

推荐答案

在C ++ 20中:

using A = decltype([]{}); // an idiom
using B = decltype([]{});
...

这是惯用的代码:这就是用C ++ 20编写给我一种独特的类型"的方式.

This is idiomatic code: that’s how one writes "give me a unique type" in C++20.

在C ++ 11中,最清晰,最简单的方法是使用__LINE__:

In C++11, the clearest and simplest approach uses __LINE__:

namespace {
  template <int> class new_type {};
}

using A = new_type<__LINE__>; // an idiom - pretty much
using B = new_type<__LINE__>;

匿名名称空间是最重要的部分.一个严重的错误是不将new_type类放在匿名名称空间中:这样,类型在翻译单元中将不再是唯一的.在您计划发货前15分钟,会发生各种各样的欢闹:)

The anonymous namespace is the most important bit. It is a serious mistake not to put the new_type class in the anonymous namespace: the types then won't be unique anymore across translation units. All sorts of hilarity will ensue 15 minutes before you plan to ship :)

这扩展到C ++ 98:

This extends to C++98:

namespace {
  template <int> class new_type {};
}

typedef new_type<__LINE__> A; // an idiom - pretty much
typedef new_type<__LINE__> B;

另一种方法是手动链接类型,并让编译器静态验证链接是否正确完成,如果不正确,则抛出错误.因此它不会很脆弱(假设魔术成功了).

Another approach would be to manually chain the types, and have the compiler statically validate that the chaining was done correctly, and bomb out with an error if you don’t. So it’d not be brittle (assuming the magic works out).

类似的东西:

namespace {
  struct base_{
    using discr = std::integral_type<int, 0>;
  };

  template <class Prev> class new_type {
    [magic here]
    using discr = std::integral_type<int, Prev::discr+1>;
  };
}

using A = new_type<base_>;
using A2 = new_type<base_>;
using B = new_type<A>;
using C = new_type<B>;
using C2 = new_type<B>;

仅需一点点魔术就可以确保A2和C2类型的行不会被编译.在C ++ 11中这种魔术是否可能是另一回事.

It takes only a small bit of magic to ensure that the lines with types A2 and C2 don’t compile. Whether that magic is possible in C++11 is another story.

这篇关于元编程:动态声明一个新的结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆