简体   繁体   中英

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM