I have in an upstream library a templated function that I want to specialize:
/// glog/logging.h
namespace google {
template <typename T>
inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v;
}
} // namespace google
I did so by defining in my code
namespace google {
template <>
inline void MakeCheckOpValueString<std::chrono::nanoseconds>(std::ostream* os, const Duration& d) {
(*os) << v.cound();
}
} // namespace google
I would like to disable this specialization at compile time (i.e. not through preprocessor macros) with something along the lines of
constexpr bool provide_my_specializations = ...;
template <std::enable_if<provide_my_specializations>>
inline void MakeCheckOpValueString<std::chrono::nanoseconds>(std::ostream* os, const Duration& d)
But I didn't find a way where to put the enable_if
into the template specialization. Is it possible to enable/disable a template specialization with sfinae, without modifying the general template?
EDIT:
given the comment, I tried using a function overload, though fail to find the right place for sfinae disabling either
constexpr bool SWITCH = false;
namespace glog {
inline std::enable_if_t<SWITCH, void> MakeCheckOpValueString(std::ostream* os, const Duration& v) {
(*os) << v.count();
}
}
EDIT2:
The function that I'm trying to specialize is not used by me, but in the upstream library itself, so I can't call a different (wrapping) object instead as that would require editing the call sites upstream.
(turns out that makes the overloading instead of specialization trickier - while not impossible
// glog/logging.h
namespace google {
template <typename T>
inline void MakeCheckOpValueString(std::ostream* os, const T& v) {
(*os) << v;
}
tempate <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext) {
base::CheckOpMessageBuilder comb(exprtext);
MakeCheckOpValueString(comb.ForVar1(), v1);
MakeCheckOpValueString(comb.ForVar2(), v2);
return comb.NewString();
}
// my code
// non-templated overload of MakeCheckOpValueString needs to go here
#include <glog/logging.h>
// template specialization of MakeCheckOpValueString can go here
/*
code that eventually instantiates MakeCheckOpString comes here
*/
)
std::enable_if_t<false>
is invalid (for any specialization).
To make it SFINAE friendly, you have to make the condition dependent:
constexpr bool SWITCH = false;
namespace glog {
template <bool b = SWITCH>
std::enable_if_t<b> MakeCheckOpValueString(std::ostream* os, const Duration& v) {
(*os) << v.count();
}
}