I'm trying to forward a generic parameter pack from a base function, but trouble doing so, particularly if there are non-literal non-reference types in the type list
Considering the following example:
#include <utility>
#include <iostream>
#include <future>
#include <vector>
template < typename... Args >
class BaseTemplate {
public:
BaseTemplate() = default;
virtual ~BaseTemplate() = default;
virtual std::future< void > call(Args... args) {
return std::async(std::launch::async, [this, &args... ] {
// ..
first(std::forward<Args>(args)...);
second(std::forward<Args>(args)...);
third(std::forward<Args>(args)...);
// ...
});
}
protected:
virtual void first(Args...) { /* ... */ }
virtual void second(Args...) = 0;
virtual void third(Args...) { /* ... */ }
};
class SomeType {
public:
explicit SomeType(std::vector< float >* data) : ptr(data) { /* ... */ }
~SomeType() = default;
// ...
// protected:
float member = 5.6;
std::vector< float >* ptr;
};
class Derived1 : public BaseTemplate< int, float, SomeType > {
public:
using Base = BaseTemplate< int, float, SomeType >;
Derived1() : Base() { /* ... */ }
~Derived1() = default;
protected:
void second(int, float, SomeType obj) override {
std::cout << "Derived1::" << __func__ << " (" << obj.member << ")" << std::endl;
printf("%p\n", obj.ptr);
for (const auto& val : *(obj.ptr)) {
std::cout << val << std::endl;
}
}
};
class Derived2 : public BaseTemplate< int, float, const SomeType& > {
public:
using Base = BaseTemplate< int, float, const SomeType& >;
Derived2() : Base() { /* ... */ }
~Derived2() = default;
protected:
void second(int, float, const SomeType& obj) override {
std::cout << "Derived2::" << __func__ << " (" << obj.member << ")" << std::endl;
printf("%p\n", obj.ptr);
for (const auto& val : *(obj.ptr)) {
std::cout << val << std::endl;
}
}
};
int main(int argc, char const *argv[]) {
std::vector< float > data {0, 1, 2, 3};
SomeType obj(&data);
Derived1 foo1;
Derived2 foo2;
// auto bar1 = foo1.call(1, 5.6, obj); // Segmentation fault
auto bar2 = foo2.call(1, 5.6, obj); // OK
// ...
// bar1.wait();
bar2.wait();
return 0;
}
Everything works as intended if SomeType
is passed by reference, but segfaults if passed by value. What is the proper way to use std::forward<>()
in order to account for both cases?