The following compiles on Visual Studio:
template<typename ArgType, typename ReturnType>
struct Test
{
using FunctionPointerType = std::conditional_t<std::is_same_v<ArgType, void>, ReturnType(*)(), ReturnType(*)(ArgType)>;
FunctionPointerType Func;
};
int main()
{
Test<void, char> tt;
}
But does not compile on Linux g . The error I get is
error : invalid parameter type ‘void’
I know I cannot use void in templates, which is why I have used conditional_t
and is_same_v
.
I cannot see what is incorrect, can someone please tell me?
CodePudding user response:
Not really an answer to your question (Why doesn't my code work), but this works:
template<typename ArgType, typename ReturnType>
struct Test
{
using FunctionPointerType = ReturnType(*)(ArgType);
FunctionPointerType Func;
};
template<typename ReturnType>
struct Test<void, ReturnType>
{
using FunctionPointerType = ReturnType(*)();
FunctionPointerType Func;
};
CodePudding user response:
template<typename ArgType, typename ReturnType>
struct Test
{
using FunctionPointerType = std::conditional_t<std::is_same_v<ArgType, void>, ReturnType(*)(), ReturnType(*)(ArgType)>;
FunctionPointerType Func;
};
conditional_t
takes 3 arguments. A bool
and 2 types.
The right type, when ArgType
is void
, is ReturnType(*)(void)
-- not a legal type.
The error happens immediately.
MSVC has a bad habit of treating templates like macros.
Something like this:
template<class...Args>
struct Apply {
template<template<class...>class Z>
using To = Z<Args...>;
};
template<class R, class...Args>
using FunctionPtr = R(*)(Args...);
template<typename ArgType, typename ReturnType>
struct Test
{
using FunctionPointerType =
std::conditional_t<
std::is_same_v<ArgType, void>,
Apply<ReturnType>,
Apply<ReturnType, ArgType>
>::template To<FunctionPtr>;
FunctionPointerType Func;
};
builds 2 pack appliers, then applies one to FunctionPtr
depending on which one is picked.
Here, I avoid forming X(void)
types until after the condition branch has occurred.