从父级的模板参数之一推断出完整的类型

发布于 2025-01-15 15:00:40 字数 1660 浏览 3 评论 0原文

我想获取具有特定模板参数(键)的父级的类型名。

例如,如果我有一个父 MyParent,我希望能够从我的孩子那里获取该类型(MyParent)只是“1”。如果我有 MyParent 我希望能够仅用“2”获取该类型(MyParent)。

基本上,我想从“键”(1、2、3等)获取类型名(MyParent、MyParent等),

我正在使用C++中的MSVC编译器20模式。

下面的工作代码正是这样做的(但它有一个缺点):

#include <iostream>

template<std::size_t key>
class KeyClass {};

template<class Type, std::size_t key>
class parent
{
    using keyclass = KeyClass<key>;
    using self = parent<Type, key>;
public:
    template<std::same_as<keyclass> T>
    static self GetType() {}
};

class test :
    public parent<int, 1>,
    public parent<float, 2>
{
public:
    using parent<int, 1>::GetType;
    using parent<float, 2>::GetType;
};

int main()
{
    std::cout << typeid(decltype(test::GetType<KeyClass<1>>())).name() << std::endl;
    std::cout << typeid(decltype(test::GetType<KeyClass<2>>())).name() << std::endl;
}

这将按预期打印:“classparentclassparent”。我可以自由地使用这些类型,获取它们的静态成员并用它们做其他事情,这正是我想要的。

缺点是我必须明确指定我正在使用我父母的每一位的 GetType 方法。这是相当蹩脚的,因为我必须将所有内容输入两次(继承一次,然后指定“使用”)。想象一下有几十个键......

有没有其他方法可以在不重复我的代码的情况下做到这一点?例如,是否有任何方法可以以某种方式为一行中的所有父级指定“using GetType”?或者让它们自动继承或其他什么,这样我就不必指定“使用”?

或者也许有一种不同的方法来做我想做的事情(在编译时从某个键(模板参数)获取类型,例如 1 应该返回 Myparent, 2 应该返回MyParent)?

我不想为此使用预处理器。

I want to get the typename of the parent that has a specific template parameter(key).

For example, if I have a parent MyParent<int, 1>, I want to be able to get that type(MyParent<int, 1>) from my child with just '1'. If I have MyParent<float,2> I want to be able to get that type(MyParent<float, 2>) with just '2'.

Basically, I want to get a typename (MyParent<float, 1>, MyParent<int, 2> etc.) from a "key" (1, 2, 3 etc.)

I'm using MSVC compiler, in C++20 mode.

Here's working code that does exactly that (but it has one downside):

#include <iostream>

template<std::size_t key>
class KeyClass {};

template<class Type, std::size_t key>
class parent
{
    using keyclass = KeyClass<key>;
    using self = parent<Type, key>;
public:
    template<std::same_as<keyclass> T>
    static self GetType() {}
};

class test :
    public parent<int, 1>,
    public parent<float, 2>
{
public:
    using parent<int, 1>::GetType;
    using parent<float, 2>::GetType;
};

int main()
{
    std::cout << typeid(decltype(test::GetType<KeyClass<1>>())).name() << std::endl;
    std::cout << typeid(decltype(test::GetType<KeyClass<2>>())).name() << std::endl;
}

This prints as expected: "class parent<int,1> class parent<float,2>". I can freely use those types, get their static members and do other stuff with them, and that's exactly what I want.

The downside is that I have to explicitly specify that I'm using the GetType method from every one of my parents. Which is quite lame, since I have to type everything twice (inheriting once, then specifying 'using'). Imagine having tens of keys ...

Are there any other ways to do this without repeating my code? For example, is there any way to specify 'using GetType` for all the parents in one line somehow? Or to make them automatically inherited or something, so that I don't have to specify 'using' at all?

Or maybe there's a different way to do what I want (to get a type at compile-time from some key (a template parameter), for example 1 should return Myparent<int, 1>, 2 should return MyParent<int, 2>)?

I don't want to use the preprocessor for this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

躲猫猫 2025-01-22 15:00:40

为了避免为每个父类的成员编写 using 声明,您可以编写一个可变参数类模板包装器,为所有类型公开此成员(如所示的重载器模式< a href="https://en.cppreference.com/w/cpp/language/using_declaration" rel="nofollow noreferrer">此处)

template<typename... Ts>
struct Bases : Ts...
{
    using Ts::GetType...; 
};

现在你的 test 类可以继承从这个包装器作为

class test : public Bases<parent<int, 1>, 
                          parent<float, 2>>
{};

这是一个演示

To avoid having to write a using declaration for the members of each of the parent classes, you can write a variadic class template wrapper that exposes this member for all of the types (as in the Overloader pattern shown here)

template<typename... Ts>
struct Bases : Ts...
{
    using Ts::GetType...; 
};

And now your test class can just inherit from this wrapper as

class test : public Bases<parent<int, 1>, 
                          parent<float, 2>>
{};

Here's a demo

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文