Edit: выполнено переписывание предоставленного кода на основе отзывов, чтобы помочь проиллюстрировать проблему
Скажем, у меня есть метод template<T> do_foo(T)
, и я использую его исключительно с использованием std::enable_if
для определения возвращаемых значений
Это позволяет мне писать для него подписи, такие как
// templates_top.h
template<typename T>
std::enable_if_t<std::is_fundamental<T>::value, int> do_foo(T bb)
{
return 0;
}
Я также могу добавить больше определений для do_foo
дальше по строке - templates_top.h
не требует объявлений fwd для все, что могло go в do_foo
- то, что когда-либо вызывает do_foo
, просто должно быть.
Теперь предположим, что у меня есть пара классов, для которых реализация do_foo
в идеале not быть в шапке
// templates_a.h
#include "./templates_top.h"
#include "./templates_b.h"
class LocalTypeA {
public:
LocalTypeB* internal_;
};
template<typename T>
std::enable_if_t<std::is_same<T, LocalTypeA>::value, int> do_foo(T bb)
{
// Some detailed business logic
// With recursive do_foo for member
return do_foo<LocalTypeB>(*(bb.internal_));
}
// templates_b.h
#include "templates_top.h"
class LocalTypeB {
public:
bool the_val = false;
};
template<typename T>
std::enable_if_t<std::is_same<T, LocalTypeB>::value, int> do_foo(T bb)
{
// Some detailed business logic here
// specific to LocalTypeB that ideally isn't in a header
// Also not that do_foo is called recursively for the std::is_fundamental type
return do_foo<bool>(bb.the_val);
}
Все это работает нормально, когда все в шапке. Но теперь - мы хотим убрать эту сложную бизнес-логику c из заголовков.
Мы не можем полностью специализировать ее, например, template<> do_foo(LocalTypeB)
, поскольку не существует общей c реализации template<typename T> do_foo(T)
. Если мы сделаем этот общий c один - тогда перегрузка std::is_fundamental
станет неоднозначной.
Есть ли способ написать этот сценарий, чтобы
templates_top.h
сохранял его игнорирование LocalTypeA/B
и использование std::is_fundamental
- Разрешение перегрузкам для
LocalTypeA/B
перемещаться в их собственные соответствующие имп-файлы и при этом разрешать std::enable_if
подписанные функции
FWIW - моим целевым стандартом C ++ является C ++ 11, но я предполагаю, что функции из C ++ 14/17 могут сделать это возможным, поэтому они тоже хороши.
Стоит отметить - это довольно большое упрощение реальной проблемы, с объяснением которой у меня возникли некоторые проблемы - я ищу больше способов решить суть конфликта типов в гораздо большем масштабе.
Пример кода здесь - компилировать как g++ main_a.cpp
или g++ main_b.cpp