在VS2017中编译错误C2027但在小对象优化时编译不是Clang

时间:2017-12-07 02:27:04

标签: c++ templates compiler-errors

所以我试图在我的项目中实现小对象优化,但是我遇到了一个奇怪的编译器错误。以下是一些重现问题的简化代码:

#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);
}

基本上,我需要获取一个任意对象,将它放在一个包装器中,并在padding中实例化一个包装器的实例,但我需要使用一个包装器用于可以放入填充的类型和另一个用于填充的类型太大的类型(其中一个包装器将对象存储到位,而另一个包装器为其分配外部空间)。显然我想支持完美的转发。

不幸的是,VS2017给了我以下编译器错误:error C2027: use of undefined type 'Wrapper<decay<_Ty>::type>'。我可以使用Wrapper<T>而不是Wrapper<std::decay_t<T>>编译它,但我认为我需要使用衰减类型。 Clang编译得很好。

那么这里的问题是什么?我有点卡住了。

1 个答案:

答案 0 :(得分:3)

可能是VS编译器中的错误。

我可以使用默认类型而不是默认值来使用稍微不同的sfinae条件进行编译:

#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);
}

没有真正解释为什么这应该更好,它只是我经常使用的形式。