std::conditional - 即使在测试 'void' 时,参数类型“void”也是无效的
std::conditional - Invalid parameter type ‘void’ even when testing for 'void'
以下在 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;
}
但不能在 Linux g++ 上编译。我得到的错误是
error : invalid parameter type ‘void’
我知道我不能在模板中使用 void,这就是我使用 std::conditional_t
和 std::is_same_v
.
的原因
我看不出哪里不对,有人可以告诉我吗?
不是您问题的真正答案(为什么我的代码不起作用),但这有效:
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;
};
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
接受 3 个参数。一种bool
和2种。
正确的类型,当 ArgType
是 void
时,是 ReturnType(*)(void)
-- 不是合法类型。
错误立即发生。
MSVC 有个坏习惯,就是把模板当作宏来处理。
像这样:
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;
};
构建 2 包应用程序,然后将一个应用到 FunctionPtr
,具体取决于选择的是哪一个。
在这里,我避免在条件分支发生之前形成 X(void)
类型。
在 std::conditional_t<B, T, F>
中,true
和 false
专业化都应该具有有效类型 T
以及 F
。在您的情况下,由于 F
推断为无效的 char(*)(void)
类型,因此无法在此处使用 std::conditional
。
我会建议一个辅助特征 function_ptr_t
作为替代
#include <type_traits>
template<typename RetType, typename... Args> struct function_ptr final {
using type = RetType(*)(Args...);
};
template <typename RetType> struct function_ptr<RetType, void> final {
using type = RetType(*)();
};
// alias helper
template<typename RetType, typename... Args>
using function_ptr_t = typename function_ptr<RetType, Args...>::type;
template<typename RetType, typename... Args>
struct Test
{
function_ptr_t<RetType, Args...> Func;
};
请注意,我已经交换了 class 模板 Test
中的模板参数,并将第二个模板参数设为可变参数,这样 Test<char>
将导致char(*)()
.
类型的成员函数指针
这意味着以下将起作用:
Test<char> tt1;
static_assert(std::is_same_v<char(*)(), decltype(tt1.Func)>, " are not same!");
Test<char, void> tt2;
static_assert(std::is_same_v<char(*)(), decltype(tt2.Func)>, " are not same!");
Test<void, double> tt3;
static_assert(std::is_same_v<void(*)(double), decltype(tt3.Func)>, " are not same!");
如果这不是您想要的,请将可变参数模板参数替换为普通参数。
以下在 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;
}
但不能在 Linux g++ 上编译。我得到的错误是
error : invalid parameter type ‘void’
我知道我不能在模板中使用 void,这就是我使用 std::conditional_t
和 std::is_same_v
.
我看不出哪里不对,有人可以告诉我吗?
不是您问题的真正答案(为什么我的代码不起作用),但这有效:
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;
};
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
接受 3 个参数。一种bool
和2种。
正确的类型,当 ArgType
是 void
时,是 ReturnType(*)(void)
-- 不是合法类型。
错误立即发生。
MSVC 有个坏习惯,就是把模板当作宏来处理。
像这样:
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;
};
构建 2 包应用程序,然后将一个应用到 FunctionPtr
,具体取决于选择的是哪一个。
在这里,我避免在条件分支发生之前形成 X(void)
类型。
在 std::conditional_t<B, T, F>
中,true
和 false
专业化都应该具有有效类型 T
以及 F
。在您的情况下,由于 F
推断为无效的 char(*)(void)
类型,因此无法在此处使用 std::conditional
。
我会建议一个辅助特征 function_ptr_t
作为替代
#include <type_traits>
template<typename RetType, typename... Args> struct function_ptr final {
using type = RetType(*)(Args...);
};
template <typename RetType> struct function_ptr<RetType, void> final {
using type = RetType(*)();
};
// alias helper
template<typename RetType, typename... Args>
using function_ptr_t = typename function_ptr<RetType, Args...>::type;
template<typename RetType, typename... Args>
struct Test
{
function_ptr_t<RetType, Args...> Func;
};
请注意,我已经交换了 class 模板 Test
中的模板参数,并将第二个模板参数设为可变参数,这样 Test<char>
将导致char(*)()
.
这意味着以下将起作用:
Test<char> tt1;
static_assert(std::is_same_v<char(*)(), decltype(tt1.Func)>, " are not same!");
Test<char, void> tt2;
static_assert(std::is_same_v<char(*)(), decltype(tt2.Func)>, " are not same!");
Test<void, double> tt3;
static_assert(std::is_same_v<void(*)(double), decltype(tt3.Func)>, " are not same!");
如果这不是您想要的,请将可变参数模板参数替换为普通参数。