当前位置: 首页 > 知识库问答 >
问题:

std::conditional-参数类型“void”无效,即使在测试“void”时也是如此

淳于昊然
2023-03-14

以下内容在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\u t和std::is\u same\u v的原因。

我看不出有什么不对,有人能告诉我吗?

共有3个答案

闾丘博超
2023-03-14
匿名用户

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)类型。

仉联
2023-03-14

在标准中::conditional\u t

我会建议一个助手traitsfunction\u 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;
};

查看演示

请注意,我交换了类template Test中的模板参数,并将第二个模板参数设置为变量,以便测试

这意味着以下措施将起作用:

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!");

如果不是,您希望将可变参数模板参数替换为正常参数。

顾俊哲
2023-03-14

这并不能真正回答您的问题(为什么我的代码不起作用),但这是可行的:

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;
};
 类似资料:
  • 我正在编写一个小的简单程序,它使用pthreads实现了一个循环执行时间表。我首先编写了没有pthreads的程序,现在试图将参数正确地传递到pthread_create中。我知道args是: int pthread_create(pthread_t*thread,const pthread_attr_t*attr,void*(*start_routome)(void*),void*arg);

  • 在下面的代码中,为什么模板函数的显式扩展无法编译,而条形扩展却成功编译?实时链接-https://godbolt.org/z/o8Ea49KEb 请注意,这两个函数的主体中都使用了模板参数T2,唯一的区别是已手动替换条形图的函数参数。 这个问题是在阅读了std::c条件-无效参数类型“无效”后提出的,即使在测试“无效”并试图简化问题时也是如此。

  • 问题内容: 我正在为apache HttpClient包实现一个,如下所示: 但我希望函数不返回任何值,即。这可能吗?由于不是有效的Java类型,因此以下内容无法编译: 我想可以替换为以返回对象,但这并不是我真正想要的。 问 :是否有可能安排在这样一种方式,我可以返回此回调局面从? 问题答案: 泛型仅处理对象类。泛型不支持void和基本类型,您不能将它们用作参数化类型。您必须改用Void。 你能说

  • void 类型 万能类型,在需要时再具体指定;在描述一段还没有具体使用的内存时需要使用void类型。 void * 类型的指针指向的内存是尚未确定类型的,因此我们后续可以使用强制类型转换,强行将其转为各种类型。这就是void类型的最终归宿——被强制类型转换成一个具体的类型。 void * 万能指针,void * 可以指向任何类型的数据,在32位系统下,占4个字节 void* malloc(size

  • 问题内容: 我正在玩Java 8,以了解如何发挥一流公民的作用。我有以下片段: 我想做的是使用方法引用将方法传递给方法。要编译会产生以下错误: 编译器抱怨。我不知道如何在代码的签名中指定函数接口的类型。我知道我可以简单地改变的返回类型来,然后返回。但是,在某些情况下,无法更改我想传递到其他地方的方法。有没有简单的方法可以重复使用? 问题答案: 您正在尝试使用错误的接口类型。在这种情况下,函数类型是

  • 问题内容: 更新到xcode 8 beta 6后,出现错误 无法将’()-> Void’类型的值分配给’(()-> Void)!’ 在以下func块的第三行: 关于修复的任何建议? 问题答案: 看来您的问题与此有关: SE-0103 尝试将您的方法标头追踪到: 与往常一样,来自新Beta的诊断消息是如此混乱和不足,但是将您的媒体资源设置为非可选将为您提供更多有用的信息。