In the class I am currently writing, I consider it to be very important that most of its private member variables remain const
. As such, I have opted to use an initialization object that is not fully declared in the header file:
// 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, ...}) {}
However, this seems to break down if one of the constructor arguments or member variables must be of the type parameter type:
// 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, ...}) {}
I have tried some alternative syntaxes (such as Foo<T>::Foo(template<> FooInitializer<T> &&initializer)
to no avail. I am opposed to temporary heap allocation, and I am trying to avoid introducing FooInitializer
into the header's namespace due to essentially duplicate declarations of the member variables. I was considering the possibility of storing a const FooInitializer
instance itself as the only member variable of Foo
, but unfortunately that would make variables like memberVariable
in the example above int *const
, not const int *const
. They cannot be C containers because they are allocated in device memory by CUDA functions.
Is there an alternative approach I have not considered?
CodePudding user response:
Foo(class FooInitializer<T> &&initializer);
Whereas you can declare (non-template) classes inside function declaration (int bar(struct S s);
), I don't think you can for template classes.
I am trying to avoid introducing
FooInitializer
into the header's namespace due to essentially duplicate declarations of the member variables.
but you can still forward declare the class:
template <typename> class FooInitializer;
template<typename T>
class Foo
{
// ...
Foo(FooInitializer<T> &&initializer);
// ...
};