C ++模板难以理解的行为

时间:2014-06-13 14:07:33

标签: c++ templates

首先 - 这段代码很糟糕,我知道,它是用于试验模板的,但我真的不知道它是如何/为什么它的工作原样。

代码:

#include <iostream>
#include <vector>
#include <string>

template <typename T>
class Container {
public:
    Container() { 
        std::cout << "Container()" << std::endl;
    }
    Container(const Container& other){
        std::cout << "Container(const Container& other)" << std::endl;
    }
    template <typename A>
    Container(const A& other) {
        std::cout << "Container(const A& other)" << std::endl;
    }
    Container(const std::vector<int>& other) { 
        std::cout << "Container(const std::vector<int>& other)" << std::endl;
    }
    ~Container() { 
        std::cout << "~Container()" << std::endl;
    }
};

int main(){
    Container<int> c1;
    Container<int> c2(c1);
    Container<int> c3(std::vector<int>());
    Container<int> c4();
    Container<int> c3(std::string());

    return 0;
}

输出:

Container()
Container(const Container& other)
Container()
~Container()
~Container()
~Container()

问题是:

  1. 它编译! (使用-Wall,-Wextra只显示未使用的其他参数)为什么?
  2. 它运行! (我可能期待一些UB,但我不知道它的起源)。为什么?
  3. 这里发生了什么?为什么c3变量似乎被完全忽略了?我有点想法,也许它不能扩展模板,但为什么它不会在编译期间失败?

    编译器:gcc版本4.8.1

2 个答案:

答案 0 :(得分:5)

由于两个c3变量都是函数声明(正如Angew在注释中指出的那样),你最终会声明重载函数。

您声明一个带有std::vector<int>()参数的重载和一个带有std::string()参数的重载。这两个重载不会发生冲突,代码会编译。

答案 1 :(得分:1)

如前所述:c3,c4和c5是函数声明,但没有人说明如何解决它。

Container<int> c3((std::vector<int>())); // add parentheses to clarify it's not a function declaration
Container<int> c4; // remove parentheses
Container<int> c3((std::string())); // add parentheses