You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中为何模板构造函数优先级高于拷贝/移动构造函数?

问题:为何模板通用构造函数被选中而非拷贝(或移动)构造函数?

请看以下程序:

#include <variant>

struct A{
    A() {}
    ~A() {}
    A(const A&) {}
    A& operator = (const A&) { return *this;}
    A(A&&) {}
    A& operator = (A&& ) { return *this; }

    using var = std::variant<int, float>;

    var v;

    template<typename T>
    A(T&& t): v(std::forward<T>(t)) {}

};

struct B
{
    A m_a;
    B(A a) : m_a(a) //calls template constructor instead of copy!
    {}
};

核心原因

模板构造函数的推导结果比拷贝构造函数的匹配度更高,具体分析如下:

  • 在B的构造函数中,m_a(a)里的a是非const的左值(B(A a)的参数a是传值进来的左值)。
  • 拷贝构造函数A(const A&)接受的是const A的引用,匹配时需要给a添加const限定,属于低一级的匹配。
  • 模板构造函数template<typename T> A(T&& t)会通过引用折叠规则推导为T=A&,实例化出A(A& t),它直接接受非const左值a,无需任何限定转换,匹配度完全贴合。

根据C++重载决议规则:可行重载中匹配度最高的函数会被选中,因此模板构造函数优先被调用。

解决办法

若要让拷贝构造函数优先生效,可采用以下两种方式:

  1. 添加非const版本的拷贝构造函数:
A(A&) {} // 非模板函数优先级高于模板实例化函数
  1. 给模板构造函数添加SFINAE约束,排除T为A相关类型的情况:
template<typename T, std::enable_if_t<!std::is_same_v<std::decay_t<T>, A>, int> = 0>
A(T&& t): v(std::forward<T>(t)) {}

补充说明:我认为这并非《为何未调用此模板移动构造函数?》的重复问题,因为该问题询问的是为何模板构造函数未被调用?,而我询问的是为何模板构造函数被调用?,二者问题恰好相反。:)

内容的提问来源于stack exchange,提问作者Khurshid Normuradov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 18:05:18