I'm currently porting my library, but my dark template magic won't get compiled with GCC 5.3
This fragment works as expected when compiled with MSVC2015 Update 2
template<typename vreal =
std::enable_if<std::is_vreal<vreal>::value,
floatType>::type>
inline vreal foo(vreal bar)
{
return bar;
}
template<typename vreal =
std::enable_if<std::is_vreal<vreal>::value,
floatType>::type>
struct bar { vreal i; };
GCC complains about "vreal was not defined in current scope (WTF?)"
What I've tried so far:
Rewrite the upper template fragment to
template<typename vreal,
typename enable = typename std::enable_if<std::is_vreal<vreal>::value != 0>::type>
But this doesn't work either. It breaks much much later in the code and I assume that it's due the introduction of the additional template param.
Also, I don't understand why I had to introduce the comparison with 0. Without it gcc complained about missing 'type' on enabled_if.
So, the main question is: how to get the same SFINAE logic (compile ONLY if the argument is vreal) WITHOUT additional arguments.
I could rewrite that to return type SFINAE - but that would be a lot of work which I'd like to avoid (differentiating between functions, classes, structs, typedefs / usings...) even though it's wrapped in a macro.
template<typename vreal>
typename std::enable_if<is_vreal<vreal>, vreal>::type inline vreal .....
This is not valid C++:
for many reasons. It uses a symbol in
stdthat isn't instd(is_vreal), which means your program is ill-formed. It uses a tokenfloatTypethat is not defined (you did post a [MCVE] right?). It usesvrealbefore it is in scope, in the definition ofvreal.I have no idea what it is supposed to mean, other than your seeming belief that it does SFINAE magic: it states that if
vrealpasses theis_vrealtest, it should be the typefloatTypeby default. But in order to reach this point, you had to have the typevrealalready, so the default type doesn't seem to matter.Also,
::typeis not a type in a dependent context:, sostd::enable_if<std::is_vreal<vreal>::value, floatType>::typeshould complain that you are using a non-type named::typein a context where a type is expected. You need to dotypenam estd::enable_if<std::is_vreal<vreal>::value, floatType>::type.You seem to also state that you are using macros to generate code. That was a poor decision.
As far as I can tell, simply removing the
enable_ifclause completely will solve your problem for most cases.The exception is for functions, because there can be overloads, you can introduce a SFINAE helper.
Ditch the macro completely. Class and function templates work significantly differently anyhow.
For classes/structs:
because there really isn't another alternative -- there isn't the concept of overloading with structures/classes like there is with functions.
For functions, we want a SFINAE test so we can overload:
if the function returns a differnet type, do
You can do this as you sweep to remove your macro.