I am writing a fixed size container type, with placement new. When I was testing it I figured it out my "emplace_back()" like function does not compile if the type T has explicit ctor.
Here is a code sample (with missing delete call, etc):
#include <iostream>
template <typename T>
struct TestType
{
explicit TestType(T value) // removing explicit makes it a compileable code
{
std::cout << value << std::endl;
}
};
template <typename... Args>
void emplace(TestType<int>* buffer, Args&&... args)
{
// placement new // compile time error in this line
new (buffer) TestType<int>(std::forward<TestType<int>>(args)...);
}
int main()
{
TestType<int>* buffer;
buffer = (static_cast<TestType<int>*>(::operator new(sizeof(TestType<int>) * 10)));
emplace(buffer, 5);
return 0;
}
The erros is: " In instantiation of 'void emplace(TestType*, Args&& ...) [with Args = {int}]': 24:22: required from here 16:64: error: no matching function for call to 'forward(int&)'"
There are some similar questions on stackoverflow, however these are mostly about std::map, probably my question is different. (And if not, I still don't understand what is going on.)
In the case of (e.g.) std::vector emplace_back() works with any T type with explicit ctor in them, why doesn't it work with my container type? This compiles fine:
#include <iostream>
#include <vector>
template <typename T>
struct TestType
{
explicit TestType(T value)
{}
};
int main()
{
std::vector<TestType<int>> vector;
vector.emplace_back(5);
return 0;
}
Thank you for your help!
You're specifying
TestType<int>
as template argument forstd::forward
asstd::forward<TestType<int>>(args)...
, means you're forwarding arguments asTestType<int>
. The argument being passed is tried to be converted toTestType<int>
implicitly, which doesn't work because the converting constructor is marked asexplicit
.You should specify
Args
as template argument forstd::forward
, i.e. forward the arguments as: