首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >C++中的模板化成员变量

C++中的模板化成员变量
EN

Stack Overflow用户
提问于 2021-01-16 07:44:09
回答 2查看 115关注 0票数 0

在编写模板化代码时,我经常发现自己需要在成员变量中存储模板类型的实例。例如,我可能需要缓存一个值,以便稍后使用。我希望能够将我的代码写成:

代码语言:javascript
运行
复制
struct Foo
{
    template
    T member;
    
    template
    void setMember(T value)
    {
        member = value;
    }

    template
    T getMember()
    {
        return member;
    }
};

其中成员在使用时是专门化的。我的问题是:

这种模板化的成员变量在当前的C++生成编码工具中是可能的吗?

如果没有,有没有关于这种语言特性的建议?

如果没有,有没有技术上的原因导致这种情况不可能发生?

很明显,我不想列出所有可能的类型(例如,在std::variant),因为这不是生成式编程,如果库的用户与作者不同,则不可能实现。

编辑:我认为这在某种程度上回答了我上面的第三个问题。原因是今天的编译器不能将对象的实例化推迟到整个程序解析之后:

https://stackoverflow.com/a/27709454/3847255

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-16 07:51:04

通过组合现有的设施,这在库中是可能的。

最简单的实现是

代码语言:javascript
运行
复制
std::unordered_map

这有点低效,因为它将每个 std::type_index 对象存储两次(一次在键中,一次在每个 std::any 中),因此具有自定义透明哈希和比较器的 std::unordered_set 会更有效;不过,这将是更多的工作。

Example.

正如你所说,图书馆的用户可能与作者不一样;特别是 Foo 的析构函数不知道设置了哪些类型,但它必须定位那些对象并调用它们的析构函数,注意 Foo 实例之间使用的类型集可能不同,因此这些信息必须存储在运行时Foo 中的容器。如果您对 std::type_index 和 std::any 隐含的 RTTI 开销持谨慎态度,我们可以将它们替换为较低级别的等效项。对于 std::type_index ,您可以使用指向静态标签变量模板实例化(或任何类似工具)的指针,对于 std::any 您可以使用类型擦除的 std::unique_ptr ,其中删除器是函数指针

代码语言:javascript
运行
复制
using ErasedPtr = std::unique_ptr;
std::unordered_map member;
struct tag {};
template inline static tag type_tag;

    member.insert_or_assign(&type_tag, ErasedPtr{new T(value), [](void* p) {
        delete static_cast(p);
    }});

Example.

请注意,一旦将 std::unique_ptr 的删除器设为函数指针,它就不再是默认可构造的,因此我们不能再使用 operator[] 而必须使用 insert_or_assign 和 find。(同样,我们有同样的 DRY 违规/低效率,因为删除器可以用作映射的键;利用这一点留给读者作为练习。)

票数 1
EN

Stack Overflow用户

发布于 2021-01-16 07:56:42

这种模板化的成员变量在当前的C++生成编码工具中是可能的吗?

不,不完全是你所描述的。可以将封闭的类作为模板,并使用模板参数来描述类成员的类型。

代码语言:javascript
运行
复制
template< typename T >
struct Foo
{
    T member;
    
    void setMember(T value)
    {
        member = value;
    }
    
    T getMember()
    {
        return member;
    }
};

在C++14和更高版本中,有

可变模板

,但不能使模板成为类的非静态数据成员。

如果没有,有没有关于这种语言特性的建议?

据我所知没有。

如果没有,有没有技术上的原因导致这种情况不可能发生?

主要原因是,这将使定义类的二进制表示变得不可能。与模板相反,类是一种类型,这意味着它的表示必须是固定的,这意味着在程序中的任何位置Foo和Foo::member必须意味着相同的东西-相同的类型,相同的对象大小和二进制布局,等等。另一方面,模板不是类型(或者,在可变模板的情况下,不是对象)。当它成为一体时,它就变成了一个整体。

实例化

,并且每个模板实例化都是一个单独的类型(在可变模板-对象的情况下)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65744963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档