Home Compile error C2027 in VS2017 but not Clang with small object optimization
Reply: 1

Compile error C2027 in VS2017 but not Clang with small object optimization

nzerbzer
1#
nzerbzer Published in 2017-12-07 02:27:04Z

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.

Bo Persson
2#
Bo Persson Reply to 2017-12-07 03:31:03Z

Possibly a bug in the VS compiler.

I can get it to compile with a slightly different form of the sfinae condition, using a default type instead of a default value:

#include <type_traits>
#include <new>

template<typename T>
class Wrapper {
    T thing;
public:
    Wrapper(T&& ) {
        // ...
    }
};

class Test {
    static const size_t PADDING_SIZE = 64;
public:
    template<
        typename T, 
        class = std::enable_if_t<sizeof(Wrapper<std::decay_t<T>>) <= PADDING_SIZE>
    >
    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);
}

No real explanation of why this should work better, it's just the form I usually use.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.257194 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO