模板扣除在堆上失败但在堆栈上工作

26 c++ templates c++17

我有模板类的问题.当我在堆栈上实例化类时,它可以正常工作.当我在堆上实例化同一个类时,它会失败.(论据演绎) 我不明白为什么......

信息:我正在使用gcc 7.2.0和c ++ 17.

这里有一个例子:

#include <iostream>
#include <cstdlib>
#include <memory>

template <class ReturnType, class ClassName, class... Args>
class MethodPtr
{
public:
    typedef ReturnType (ClassName::*Method)(Args...);

    MethodPtr(ClassName* ptr, Method m) : _p(ptr), _m(m)
    {
        (ptr->*m)(4);
    }

    ClassName* _p;
    Method _m;
};

class Example
{
public:
    Example()
    {
        dotest(this, &Example::func);
    }

    template <class Ptr, class Func>
    void dotest(Ptr ptr, Func func)
    {
        // works
        MethodPtr(ptr, func);

        // don't works
        //std::make_unique<MethodPtr>(ptr, func);
        //new MethodPtr(ptr, func);

        //works
        std::make_unique<decltype(MethodPtr(ptr, func))>(ptr, func);
        new decltype(MethodPtr(ptr, func))(ptr, func);
    }

    void func(int i)
    {
        std::cout << i << std::endl;
    }
};

int main()
{
    Example example;
}
Run Code Online (Sandbox Code Playgroud)

你有避免decltype的解决方案吗?

谢谢,

Sto*_*ica 20

事实上new MethodPtr(ptr, func),推论失败的确是一个编译器错误.根据[dcl.type.class.deduct]/2:

一种用于推导的类类型的占位符,也可在所使用的 类型说明符-SEQ新型-ID类型-ID一个的新的表达,或者作为简单型说明符在一个显式的类型转换(功能符号)([expr.type.conv]).推断类类型的占位符不应出​​现在任何其他上下文中.

正如您所看到的,对新表达式显式为yes,对未明确允许的任何内容进行全面禁止.所以make_unique 不能给一个占位符.

除非您可以迁移到已经修复(或者您只需要使用make_unique)的GCC版本,否则您无法避免decltype.尝试引入类型别名以减轻不便.


Pio*_*ycz 6

在最新的gcc和clang中它起作用 - 这个new MethodPtr(ptr, func).所以对于gcc7.2 - 这是一个bug.

因为unique_ptr(new MethodPtr(ptr, func))- 它无法工作 - 因为在C++中 - 在这个层面上,有MethodPtr*- 我们无法区分unique_ptr<MethodPtr[]>unique_ptr<MethodPtr>- 所以它无法推断.