模板参数类型从类定义中扣除

Vit*_*meo 5 c++ templates template-argument-deduction c++17

是否可以在一个成员函数的定义中为类使用类模板参数推导?...或者我被迫在C++ 03中编写我的助手类?CCmake_c

考虑这种最小化和简化的场景,它构建了一系列任意函数对象:

template <typename F>
struct node;

template <typename FFwd>
node(FFwd&&) -> node<std::decay_t<FFwd>>;
Run Code Online (Sandbox Code Playgroud)

node类存储它通过完美转发初始化函数对象.我需要一个演绎指南,指向decay函数对象的类型.

template <typename F>
struct node
{
    F _f;

    template <typename FFwd>
    node(FFwd&& f) : _f{std::forward<FFwd>(f)}
    {
    }

    template <typename FThen>
    auto then(FThen&& f_then)
    {
        return node{[f_then = std::move(f_then)]
                    { 
                        return f_then(); 
                    }};
    }
};
Run Code Online (Sandbox Code Playgroud)

然后,我定义了node构造函数和一个.then返回一个新节点的continuation成员函数(它的实现是无意义的,以最小化示例的大小).如果我试图调用.then......

auto f = node{[]{ return 0; }}.then([]{ return 0; });
Run Code Online (Sandbox Code Playgroud)

...我收到一个意外的编译错误:

prog.cc: In instantiation of 'node<F>::node(FFwd&&) [with FFwd = node<F>::then(FThen&&) [with FThen = main()::<lambda()>; F = main()::<lambda()>]::<lambda()>; F = main()::<lambda()>]':
prog.cc:27:22:   required from 'auto node<F>::then(FThen&&) [with FThen = main()::<lambda()>; F = main()::<lambda()>]'
prog.cc:35:56:   required from here
prog.cc:17:46: error: no matching function for call to 'main()::<lambda()>::__lambda1(<brace-enclosed initializer list>)'
     node(FFwd&& f) : _f{std::forward<FFwd>(f)}
                                              ^
prog.cc:35:20: note: candidate: 'constexpr main()::<lambda()>::<lambda>(const main()::<lambda()>&)'
     auto f = node{[]{ return 0; }}.then([]{ return 0; });
                    ^
Run Code Online (Sandbox Code Playgroud)

wandbox上的实例

发生这种情况是因为在体内node<F>::then,node{...}创建了一个类型为的实例*this- 它不会触发参数类型推导.因此我被迫写道:

template <typename FThen>
auto then(FThen&& f_then)
{
    auto l = [f_then = std::move(f_then)]{ return f_then(); };
    return node<std::decay_t<decltype(l)>>{std::move(l)};
}
Run Code Online (Sandbox Code Playgroud)

wandbox上的实例

......这违背了演绎指南的全部目的.

有没有办法在不引入代码重复或make_node函数的情况下使用类模板参数推导?

T.C*_*.C. 7

查找node找到inject-name-name 的名称查找,从中不执行演绎.(在这种情况下执行扣除将是向后兼容性中断.)

如果要进行演绎,请对名称进行限定,以便找到命名空间成员.

template <typename FThen>
auto then(FThen&& f_then)
{
    return ::node{[f_then = std::move(f_then)]
    //     ^^
                { 
                    return f_then(); 
                }};
}
Run Code Online (Sandbox Code Playgroud)

另外,编写指南的方法更简洁

template <typename F>
node(F) -> node<F>;
Run Code Online (Sandbox Code Playgroud)