【问题标题】:Compile error C2027 in VS2017 but not Clang with small object optimization在 VS2017 中编译错误 C2027 但不是 Clang 与小对象优化
【发布时间】:2017-12-07 02:27:04
【问题描述】:

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

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

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

不幸的是,VS2017 给了我以下编译器错误:error C2027: use of undefined type 'Wrapper&lt;decay&lt;_Ty&gt;::type&gt;'。我可以用Wrapper&lt;T&gt; 而不是Wrapper&lt;std::decay_t&lt;T&gt;&gt; 编译它就好了,但我认为我需要使用衰变类型。 Clang 按原样编译它。

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

【问题讨论】:

    标签: c++ templates compiler-errors


    【解决方案1】:

    可能是 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);
    }
    

    没有真正解释为什么这会更好,这只是我通常使用的形式。

    【讨论】:

    • 编译成功,但是当我添加另一个构造函数(使用std::enable_if_t&lt;sizeof(Wrapper&lt;std::decay_t&lt;T&gt;&gt;) &gt; PADDING_SIZE)时,我得到error C2535: 'Test::Test(T &amp;&amp;)': member function already defined or declared
    • 这是一个不同的问题。您不能有两个仅在模板参数的默认值上有所不同的函数。 stackoverflow.com/a/38540922/597607
    • 你说得对,我通过向其中一个签名添加一个虚拟模板参数来修复它。它仍然在我的项目中导致编译器错误,但是我在问题中给出的示例现在可以编译,所以我想这是一个单独的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 2018-08-02
    • 2013-10-07
    • 2013-07-05
    • 2018-09-20
    • 2019-11-01
    相关资源
    最近更新 更多