【问题标题】:Can you forward declare an explicit specialization of undeclared template class?您可以转发声明未声明模板类的显式特化吗?
【发布时间】:2021-12-18 09:55:01
【问题描述】:

在我目前正在编写的课程中,我认为它的大部分私有成员变量保持const 是非常重要的。因此,我选择使用未在头文件中完全声明的初始化对象:

// foo.h

template<typename T>
class Foo {
    const int *const memberVariable; // Important detail: pointer to a heap-allocated array
    const int otherMemberVariable;
    ...

    Foo(class FooInitializer &&initializer);

public:
    Foo(int constructorArgument, ...);
}

// foo.cpp

class FooInitializer {
    int *memberVariable; // Important detail: pointer to a heap-allocated array
    int otherMemberVariable;
    ...

    FooInitializer(int constructorArgument, ...) : memberVariable(constructorArgument, ...), ... {
        cuda_function(&memberVariable, &otherMemberVariable, ..., constructorArgument, ...);
        ...
    }
}

Foo::Foo(FooInitializer &&initializer) : memberVariable(std::move(initializer.memberVariable)), ... {}

Foo::Foo(int constructorArgument, ...) : Foo({constructorArgument, ...}) {}

但是,如果构造函数参数或成员变量之一必须是类型参数类型,这似乎会崩溃:

// foo.h

template<typename T>
class Foo {
    const int *const memberVariable; // Important detail: pointer to a heap-allocated array
    const int otherMemberVariable;
    ...

    Foo(class FooInitializer<T> &&initializer);

public:
    Foo(int constructorArgument, ...);
}

// foo.cpp

template<typename T>
class FooInitializer {
    int *memberVariable;
    int otherMemberVariable;
    ...

    FooInitializer(int constructorArgument, ...) : memberVariable(constructorArgument, ...), ... {
        cuda_function(&memberVariable, &otherMemberVariable, ..., constructorArgument, ...);
        ...
    }
}

template<typename T>
Foo<T>::Foo(FooInitializer<T> &&initializer) : memberVariable(std::move(initializer.memberVariable)), ... {}

template<typename T>
Foo<T>::Foo(int constructorArgument, ...) : Foo({constructorArgument, ...}) {}

我尝试了一些替代语法(例如 Foo&lt;T&gt;::Foo(template&lt;&gt; FooInitializer&lt;T&gt; &amp;&amp;initializer) 无济于事。我反对临时堆分配,并且我试图避免将 FooInitializer 引入标头的命名空间,因为成员变量的声明本质上是重复的. 我正在考虑将const FooInitializer 实例本身存储为Foo 的唯一成员变量的可能性,但不幸的是,这会使上面示例中memberVariable 之类的变量int *const,而不是const int *const。他们不能C++ 容器,因为它们是由 CUDA 函数在设备内存中分配的。

有没有我没有考虑过的替代方法?

【问题讨论】:

  • “这似乎要崩溃了”是什么意思?不编译?没有按预期运行?
  • @talonmies 它无法编译。
  • 我在您的问题中没有看到任何编译器错误。我们都应该猜测会发生什么吗?
  • “它们不能是 C++ 容器,因为它们是由 CUDA 函数在设备内存中分配的”。没有库就不能自己写吗?
  • @Jarod42 不幸的是,这种方法并不简单,因为我需要用shared_ptr 替换所有cudaStream_t 实例,以保持我已实现的流安全功能。

标签: c++ templates cuda


【解决方案1】:

Foo(class FooInitializer&lt;T&gt; &amp;&amp;initializer);

虽然您可以在函数声明 (int bar(struct S s);) 中声明(非模板)类,但我认为模板类不能。

我试图避免将FooInitializer 引入标头的命名空间,因为成员变量的声明本质上是重复的。

但您仍然可以转发声明该类:

template <typename> class FooInitializer;

template<typename T>
class Foo
{
    // ...
    Foo(FooInitializer<T> &&initializer);
    // ...
};

Demo

【讨论】:

  • 我宁愿不要在标头的命名空间中前向声明该类,但似乎这是最接近的解决方案。
  • 您可以将其作为Foo 的内部类。 Demo
  • 这就是我最终的结果。谢谢!
猜你喜欢
  • 2015-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-29
  • 2011-01-30
  • 1970-01-01
  • 2019-11-21
  • 2018-07-05
相关资源
最近更新 更多