#include <iostream> class Person{ public: // 完美转发用于构造函数 template<typename STR> Person(STR&& n):name(std::forward<STR>(n)) { std::cout<<"tmpl-conster"<<std::endl; } Person(const Person& p):name(p.name){ std::cout<<"copy constructor"<<std::endl; } Person(Person&& p): name(std::move(p.name)){ std::cout<<"move constructor"<<std::endl; } private: std::string name; }; void Test(){ std::string str="hello"; Person p(str); // tmpl-conster Person p1("tmp");// tmp-conster; // error, 模板构造函数copy constructor 函数(有const限定符)比更适合 // 但模板构造函数不是拷贝构造函数实现,所以报错,当然在添加个非const拷贝 // 构造函数可以解决报错,最好处理时禁用模板构造函数,后调用带有const的万能引用拷贝构造函数 /* Person(Person& p):name(p.name){} */ // Person p2(p1); Person p2(std::move(p1)); // move constructor } template<typename T> using EnableIfString = typename std::enable_if<std::is_convertible<T, std::string>::value>::type; class Person1{ public: //若STR类型到std::string不是可转换,则禁用模板函数 // 写法太复杂,可以使用模板别名 //template<typename STR, typename=typename std::enable_if<std::is_convertible<STR, std::string>::value>::type> template<typename STR, typename=EnableIfString<STR>> // EnableIfString使用更简易 Person1(STR&& n):name(std::forward<STR>(n)) { std::cout<<"tmpl-conster"<<std::endl; } Person1(const Person1& p):name(p.name){ std::cout<<"copy constructor"<<std::endl; } Person1(Person1&& p): name(std::move(p.name)){ std::cout<<"move constructor"<<std::endl; } private: std::string name; }; void Test1(){ Person1 p("tmp"); Person1 p1(p);// copy constructor, p不是string类型,模板构造函数被禁用,只能调用拷贝构造函数 } int main(){ Test(); Test1(); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75