Edit: done a rewrite of the provided code from feedback to help illustrate the issue
Say I have a method template<T> do_foo(T) and that I use it purely using std::enable_if to define return values
This allows me to write signatures for it such as
// templates_top.h
template<typename T>
std::enable_if_t<std::is_fundamental<T>::value, int> do_foo(T bb)
{
return 0;
}
I can also put in more definitions for do_foo further down the line - templates_top.h doesn't need to have fwd declarations for everything that could go into do_foo - what ever invokes do_foo just has to.
Now say I have a couple of classes for which the implementation of do_foo would ideally not be in a header
// 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);
}
All that works fine when its all in the header. But now - we want to move that complex business logic out of the headers.
We can't fully-specialise it like template<> do_foo(LocalTypeB) as there is no generic implementation template<typename T> do_foo(T). If we make that generic one - then the std::is_fundamental overload becomes ambiguous.
Is there a way for me to write this scenario so that
templates_top.hpreserves its ignorance ofLocalTypeA/Band its use ofstd::is_fundamental- Allowing the overloads for
LocalTypeA/Bto moved to their own respective impl files, and still resolve thestd::enable_ifsignatured functions
FWIW - my target C++ standard is C++11, but I'm guessing features from C++14/17 may make this possible, so they are good too.
Worth stating - this is a fairly big simplification of a real problem that I've had some trouble explaining - I'm looking more for ways to solve the heart of the type conflict on a much larger scale.
Code sample here - compile as g++ main_a.cpp or g++ main_b.cpp