您能否转发声明未声明模板 class 的显式特化?

Can you forward declare an explicit specialization of undeclared template class?

在我目前正在写的class中,我认为非常重要的一点是它的大部分私有成员变量都保持const。因此,我选择使用未在 header 文件中完全声明的初始化 object:

// 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<T>::Foo(template<> FooInitializer<T> &&initializer)无济于事。我反对临时堆分配,我试图避免将FooInitializer引入header的命名空间,因为成员变量的声明基本上重复。我正在考虑将 const FooInitializer 实例本身存储为 Foo 的唯一成员变量的可能性,但不幸的是,这会使变量像 [=18] =] 在上面的示例中 int *const,而不是 const int *const。它们不能是 C++ 容器,因为它们是由 CUDA 函数在设备内存中分配的。

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

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

尽管您可以在函数声明 (int bar(struct S s);) 中声明(非模板)classes,但我认为您不能对模板 classes 进行声明。

I am trying to avoid introducing FooInitializer into the header's namespace due to essentially duplicate declarations of the member variables.

但你仍然可以转发声明class:

template <typename> class FooInitializer;

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

Demo