Объявление членской специализации шаблонного класса

Когда я специализирую (статическую) функцию членства / постоянный в шаблонном классе, я смущен как, туда, где объявление предназначено для движения.

Вот пример того, что я, что сделать - yoinked непосредственно из ссылки IBM на шаблонной специализации:

=== Пример специализации члена IBM ===

template class X {
public:
   static T v;
   static void f(T);
};

template T X::v = 0;
template void X::f(T arg) { v = arg; }

template<> char* X::v = "Hello";
template<> void X::f(float arg) { v = arg * 2; }

int main() {
   X a, b;
   X c;
   c.f(10); // X::v now set to 20
}

Вопрос, как я делю это на header/cpp файлы? Универсальная реализация находится, очевидно, в заголовке, но что относительно специализации?

Это не может войти в заголовочный файл, потому что это конкретно, ведя к повторному определению. Но если это входит в .cpp файл, код, который звонит X:: f () знающий о специализации, или мог бы он полагаться на дженерик X:: f ()?

До сих пор у меня есть специализация в .cpp только без объявления в заголовке. Я не испытываю затруднения при компиляции или даже выполнении моего кода (на gcc, не помните версию в данный момент), и это ведет себя как ожидалось - распознавание специализации. Но A) я не уверен, что это корректно, и я хотел бы знать то, что и B) моя документация Doxygen выходит wonky и очень вводящий в заблуждение (больше на том через мгновение более поздний вопрос).

То, что кажется самым естественным для меня, было бы чем-то вроде этого, объявив специализацию в заголовке и определив его в .cpp:

=== XClass.hpp ===

#ifndef XCLASS_HPP
#define XCLASS_HPP

template class X {
public:
   static T v;
   static void f(T);
};

template T X::v = 0;
template void X::f(T arg) { v = arg; }

/* declaration of specialized functions */
template<> char* X::v;
template<> void X::f(float arg);

#endif

=== XClass.cpp ===

#include 

/* concrete implementation of specialized functions */
template<> char* X::v = "Hello";
template<> void X::f(float arg) { v = arg * 2; }

... но я понятия не имею, корректно ли это. Какие-либо идеи?

14
задан Lightness Races with Monica 17 January 2012 в 00:22
поделиться

3 ответа

Обычно вы просто определяете специализации inline в заголовке, как сказал dirkgently.

Однако вы можете определить специализации в отдельных единицах трансляции, если вас беспокоит время компиляции или раздутость кода:

// x.h:
template<class T> struct X {
    void f() {}
}

// declare specialization X<int>::f() to exist somewhere: 
template<> void X<int>::f();

// translation unit with definition for X<int>::f():
#include "x.h"
template<> void X<int>::f() {
    // ...
}

Так что да, ваш подход выглядит нормально. Обратите внимание, что это можно сделать только с полными специализациями, поэтому часто это непрактично.

Подробнее см. например, Comeaus template FAQ.

11
ответ дан 1 December 2019 в 13:58
поделиться

Чтобы ответить на один из ваших вопросов: - это код, который вызывает X :: f () с учетом специализации, или он может полагаться на общий X :: f ()?

Если компилятор видит определение, которое соответствует его требованиям, тогда он будет его использовать. В противном случае он будет генерировать обычные вызовы функций.

В первом фрагменте кода вы предоставляете общее определение для X :: f (T arg) , поэтому компилятор создаст его экземпляр для любого T , кроме поплавок .

Если вы опустите общее определение, то компилятор сгенерирует вызовы, скажем, X :: f (double) , и компоновщик будет искать определение, которое может закончиться с ошибкой компоновщика.

Подводя итог: у вас может быть все в заголовках, потому что в качестве шаблонов вы не получите несколько определений. Если у вас есть только объявления, вам понадобятся определения в другом месте, чтобы компоновщик нашел их позже.

1
ответ дан 1 December 2019 в 13:58
поделиться

Поместите их все в hpp файл. Сделайте специализации и все, что вы определяете вне класса inline - это поможет справиться с множественными определениями.

4
ответ дан 1 December 2019 в 13:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: