如果是模板化的话,g ++不会调用复制构造函数吗?

Pas*_*ist 3 c++ templates

tl; dr:如果前面带有复制构造函数,则不会调用它template<typename Something>,并且Something在构造函数签名中使用它.


概念验证(ideone):

#include <cstdio>

template<typename T>
class Test {
private:
    T value_;

public:
    mutable bool has_copies;

    Test(const T& value) : value_(value), has_copies(false) {}

    template<typename Related> // remove template here to fix behavior
    Test(const Test<Related>& t) {
        printf("In copy constructor\n");
        value_ = t.value_;
        has_copies = true;
        t.has_copies = true;
    }
};

int main() {
    Test<int> t1(42);
    printf("Before constructor\n");
    Test<int> t2(t1);
    printf("After constructor:\n");
    printf("    t1 thinks it %s copies\n", t1.has_copies ? "has" : "doesn't have");
    printf("    t2 thinks it %s copies\n", t2.has_copies ? "has" : "doesn't have");
}
Run Code Online (Sandbox Code Playgroud)

输出:

Before constructor
After constructor:
    t1 thinks it doesn't have copies
    t2 thinks it doesn't have copies
Run Code Online (Sandbox Code Playgroud)

请注意如何In copy constructor打印.

使复制构造函数非模板化(即删除template<typename Related>并更改RelatedT签名)可以解决我的问题.

$ g++ --version
g++ (GCC) 6.2.1 20160830
Run Code Online (Sandbox Code Playgroud)

编译和执行命令:

g++ -Wall -Wextra -pedantic -std=c++11 -O2 -Wshadow -Wformat=2 -Wfloat-equal -Wconversion -Wlogical-op -Wcast-qual -Wcast-align -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_FORTIFY_SOURCE=2 -fsanitize=address -fsanitize=undefined -fno-sanitize-recover -fstack-protector "test.cpp" -o "test" && "test"
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?

M.M*_*M.M 5

函数模板永远不能是复制构造函数,即使实例化的类型显然使其与复制构造函数的预期签名匹配.见[class.copy/2]:

如果X类的第一个参数是X&,const X&,volatile X&或const volatile X&,并且没有其他参数或者所有其他参数都有默认参数,则类X的非模板构造函数是一个复制构造函数.

所有类都有一个隐式生成的复制构造函数,如果没有用户声明的复制构造函数(有时这可能被定义为已删除),则带有签名:

Test(Test const &) = default;
Run Code Online (Sandbox Code Playgroud)

在编写时Test<int> t2(t1);,重载决策选择复制构造函数而不是模板函数,因为非模板优先于模板,所有其他条件相同.

请注意,如果您将模板功能更改为,Test(Test<Related>& t)那么现在将通过复制构造函数选择它:"所有其他内容"不再相等,并且实例化模板以完全匹配Test<int>优先于转换添加const以匹配复制构造函数.