So I'm trying to implement small object optimization in a project of mine, but I'm running into a strange compiler error. Here's some simplified code that reproduces the issue:
#include <type_traits>
template<typename T>
class Wrapper {
T thing;
public:
Wrapper(T&& thing) {
// ...
}
};
class Test {
static const size_t PADDING_SIZE = 64;
public:
template<
typename T,
std::enable_if_t<sizeof(Wrapper<std::decay_t<T>>) <= PADDING_SIZE, int> = 0
// Error on this line ^
>
Test(T&& thing) {
new (padding) Wrapper<std::decay_t<T>>(std::forward<T>(thing));
}
char padding[PADDING_SIZE];
};
int main() {
auto t = Test(0.0f);
}
Basically, I need to take an arbitrary object, put it in a wrapper, and instantiate an instance of the wrapper in the padding, but I need to use one wrapper for types that can fit in the padding and a different one for types that are too large (one of the wrappers stores the object in place while the other allocates external space for it). And obviously I'd like to support perfect forwarding.
Unfortunately, VS2017 gives me the following compiler error: error C2027: use of undefined type 'Wrapper<decay<_Ty>::type>'
. I can compile it just fine with Wrapper<T>
rather than Wrapper<std::decay_t<T>>
, but I think I need to use the decayed type. Clang compiles it fine as is.
So what's the problem here? I'm a bit stuck.