Отлично, спасибо за цитату!

чаю поведение компоновщика C ++ относительно специализаций шаблонов. Я использую Microsoft Visual C ++ 2010 для этих экспериментов. Я не знаю, то же самое ли поведение с другими инструментальными цепочками (например, gcc).

Вот первый фрагмент кода:

// 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
}

Ожидается, что этот код не является ссылкой, потому чтоfoo<double>() имеет несколько определений, так как создается один раз вbar.cpp и однажды вmain.cpp (через специализацию). Тогда мы ожидаем,если эта программа будет ссылаться, этоbar() а такжеmain() будет использовать различные экземплярыfoo() такой, что в конце мы получим x == 1 и y == 2.

Давайте исправим ошибку ссылки, объявив специализациюfoo<double>() какstatic:

// 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
}

Теперь у нас есть x == 1 и y == 2, как мы и ожидали. (Примечание: мыдолжен использоватьstatic ключевое слово здесь: анонимное пространство имен не подойдет, так как мы не можем специализировать функцию шаблона в другом пространстве имен, чем ее объявление.)

Теперь использованиеstatic Ключевое слово довольно неинтуитивно. Как правило, специализацияfoo<double>() будет находиться где-то в заголовочном файле и, таким образом, будет помечен как встроенный, как в следующем фрагменте:

// 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
}

Этот код теперь правильно связывается, и когда мы его запускаем, мы получаем x == 2 и y == 2.Это немного удивляет: почему существует одно определениеfoo<double>()? Каково значениеinline в этом коде?

Последний фрагмент:

// 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
}

Этот случай на самом деле не удивителен: специализацияfoo<double>() больше не создается вmain.cpp (хотя декларация все еще там), так что единственный оставшийся экземпляр - этоbar.cpp.

Ответы на вопрос(1)

Ваш ответ на вопрос