Especializações de vinculação e modelo em C ++

Estou estudando o comportamento do vinculador C ++ em relação às especializações de modelo. Estou usando o Microsoft Visual C ++ 2010 para esses experimentos. Não sei se o comportamento é o mesmo com outras cadeias de ferramentas (por exemplo, gcc).

Aqui está o primeiro trecho de código:

// bar.cpp

template <typename T> int foo() { return 1; }
int bar() { return foo<double>(); }

// main.cpp

template <typename T> int foo() { return 1; }
template <> int foo<double>() { return 2; }

int bar();

int main()
{
    const int x = bar();
    const int y = foo<double>();  // doesn't link
}

Esse código não é vinculado porquefoo<double>() possui várias definições, pois é instanciado uma vez em bar.cpp e uma vez em main.cpp (via especialização). Esperaríamos então,se este programa vincular, quebar() emain() usaria instanciações distintas defoo() tal que no final teríamos x == 1 e y == 2.

Vamos corrigir o erro de link declarando a especialização defoo<double>() Comostatic:

// bar.cpp

template <typename T> int foo() { return 1; }
int bar() { return foo<double>(); }

// main.cpp

template <typename T> int foo() { return 1; }
template <> static int foo<double>() { return 2; }  // note: static

int bar();

int main()
{
    const int x = bar();          // x == 1
    const int y = foo<double>();  // y == 2
}

Temos agora x == 1 e y == 2, como esperávamos. (Nota: nósdev use ostatic palavra-chave aqui: um espaço para nome anônimo não funciona, pois não podemos especializar uma função de modelo em um espaço para nome diferente da declaração.)

Agora, o uso dostatic palavra-chave @ é pouco intuitiva. Normalmente, a especializaçãofoo<double>() residiria em algum lugar de um arquivo de cabeçalho e, portanto, seria marcado como embutido, como no seguinte snippet:

// bar.cpp

template <typename T> int foo() { return 1; }
int bar() { return foo<double>(); }

// main.cpp

template <typename T> int foo() { return 1; }
template <> inline int foo<double>() { return 2; }  // note: inline

int bar();

int main()
{
    const int x = bar();          // x == 2
    const int y = foo<double>();  // y == 2
}

Este código agora está vinculado corretamente e, quando o executamos, obtemos x == 2 ey == 2.Este é o pouco que acho surpreendente: por que existe uma única definição defoo<double>()? Qual é o significado deinline neste código?

Um último fragmento:

// bar.cpp

template <typename T> int foo() { return 1; }
int bar() { return foo<double>(); }

// main.cpp

template <typename T> int foo() { return 1; }
template <> inline int foo<double>() { return 2; }  // note: inline

int bar();

int main()
{
    const int x = bar();             // x == 1
    // const int y = foo<double>();  // note: commented out
}

Este caso não é realmente surpreendente: a especialização defoo<double>() não é mais instanciado em main.cpp (embora a declaração ainda esteja lá), a única instancia restante é a em bar.cpp.

questionAnswers(1)

yourAnswerToTheQuestion