如何在没有参数列表更改的情况下重新编译模板函数?

时间:2016-09-23 08:11:59

标签: c++ c++14

正如您在下面的代码中看到的,方法get是模板化的。

struct A
{
    int i;
    char c;
};

class SL
{
    static void* m_a;


public:

    template <class T>
    static T* get()
    {
        return static_cast<T*>(m_a);
    }
};

void* SL::m_a = new A{12, 'C'};

int main()
{
    std::cout << SL::get<A>()->i;
    return 0;
}

我不明白的是当我写SL::get<B>()时编译器如何在同一名称空间中创建两个具有相同名称的方法,两个不同的返回类型都没有参数,即没有不同参数列表?他们如何超负荷?或者理解寺庙函数生成具有相同的名称并通过重载解析来解释它们的调用是错误的?

3 个答案:

答案 0 :(得分:5)

模板 instantions 实际上是不同的函数,它们不会过载。 您可以将模板参数<B>视为函数名称的一部分。 所以SL::get<A>SL::get<B>实际上是不同的功能(虽然来自同一个模板)。

引自cppreference

  

模板参数推导发生在函数模板名称查找之后(可能涉及依赖于参数的查找)和重载解析之前。

如您所见,重载解析是一个不同的过程。

答案 1 :(得分:2)

这是特定于编译器的,你不应该太担心它。关于如何完成它的一般概念:

假设您使用2种不同类型调用模板化方法

SL::get<A>();
SL::get<B>();

编译器为这些调用生成2个新方法:

static A* get_a()
{
  // etc..
}

static B* get_b()
{
  // etc..
}

这可能因编译器而异,但它显示了编译器如何避免名称冲突。对于程序员来说,它被调用两次相同的方法,对于编译器来说,它只是由不同的代码调用的两种不同的方法。

答案 2 :(得分:1)

模板很容易name mangling。当生成确切的get时,它不再被称为get,它将被称为get@YUQIE或类似的东西。您可以查看this article以获取示例。这是实现定义的,因此不同的编译器将以不同的方式执行它。例如,在以下代码中

template <class T>
T get()
{
    return T();
}

int main()
{
    get<int>();
    get<char>();
    return 0;
}

get被gcc评为_Z3getIiEPT_v get<int>_Z3getIcEPT_v get<char>