【问题标题】:Question about providing default type for a template关于为模板提供默认类型的问题
【发布时间】:2019-04-23 21:27:52
【问题描述】:

例如,我写了如下一段代码:

struct default_type {};

template <typename U = default_type> auto func(int x, U u) {
    if constexpr(is_same<U, default_type>::value) {
        return x * 2;
    }
    else {
        return u(x);
    }
}

int main() {
    cout << "5 + 3 = " << func(5, [](int x){ return x + 3; }) << endl;
    cout << "5 * 2 = " << func(5) << endl;
}

但这会产生“没有匹配函数调用'func(int)'”的编译器错误。这样做的正确方法是什么?

【问题讨论】:

    标签: c++


    【解决方案1】:

    您提供了默认类型,但没有提供默认值。该函数仍然需要两个参数,而default_type 将被推导的参数覆盖,使其无用。

    这样做:

    template <typename U = default_type>
    auto func(int x, U u = {}) { ... } // (1)
    

    我不能通过确切的标准来支持这一点,但简而言之:U 在 模板参数推导 阶段获得(没有推导规则 - 不考虑默认函数参数,因此默认),它出现在 重载解析 阶段之前,此时默认函数参数被解释,已经知道 U 的类型,这使得列表初始化有效。


    是的,你也可以这样写:

    template <typename U = default_type>
    auto func(int x, U u = U()) { ... } // (2)
    

    或

    template <typename U = default_type>
    auto func(int x, U u = default_type()) { ... } // (3)
    

    在显式提供 U 类型时语义略有不同(我认为您不会这样做):

    func<not_the_default_type>(5);
    

    这里,(1) 和 (2) 是等价的,但是在 (3) 中,U 的构造是通过构造一个 default_type 临时的,然后转换为 not_the_default_type。


    最后,完全相反的错误是期望U 被推导出来:

    template <typename U>
    auto func(int x, U u = default_type()) { ... }
    

    事实并非如此。见this Q&A。

    【讨论】:

    • 附带说明,如果你给default_type结构一个operator()实现,那么你根本不需要constexpr:struct default_type { int operator()(int x) { return x * 2; }}; template &lt;typename U = default_type&gt; auto func(int x, U u = {}) { return u(x); }
    猜你喜欢
    • 2010-11-09
    • 1970-01-01
    • 2019-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-07
    相关资源
    最近更新 更多