在 C++ 中使用“void”模板参数

2024-03-07

采取以下最小示例:

using Type1 = std::function<void(void)>;

template <typename T>
using Type2 = std::function<void(T)>;

Type1 whyDoesThisWork;
Type2<void> andYetThisDoesNot;

如果是第二种类型别名,我会收到错误“参数可能没有‘void’类型”。 (我使用 Xcode 4.5、Clang/c++11/libc++、OS X 10.7 进行了测试。)

我觉得这很奇怪:我本来期望Type1 and Type2<void>行为相同。这里发生了什么?有没有办法重写第二个类型别名所以我can write Type2<void>并得到std::function<void(void)>而不是错误?

Edit我可能应该补充一点,我想要这样做的原因是允许类似以下内容:

template <typename ... T>
using Continuation = std::function<void(T...)>;

auto someFunc = []() -> void {
  printf("I'm returning void!\n");
};

Continuation<decltype(someFunc())> c;

Continuation<decltype(someFunc())>变成Continuation<void>我得到了错误。


简短的回答是“模板不是字符串替换”。void f(void)仅当它是别名时才有意义void f()在C++中,为了向后兼容C。

第一步是使用可变参数,如其他地方所述。

第二步是弄清楚如何映射void返回函数...好吧,也许类似std::function<void()>,或者也许是其他东西。我说也许是别的东西,因为与其他情况不同,你不能打电话std::function<void()> foo; foo( []()->void {} );——这不是真正的延续。

也许是这样的:

template<typename T>
struct Continuation
{
  typedef std::function<void(T)> type;
};

template<>
struct Continuation<void>
{
  typedef std::function<void()> type;
};

然后像这样使用它:

auto someFunc = []()->void {};
Continuation<decltype(someFunc())>::type c;

这会给你你想要的类型。您甚至可以添加 apply to 延续:

template<typename T>
struct Continuation
{
  typedef std::function<void(T)> type;

  template<typename func, typename... Args>
  static void Apply( type const& cont, func&& f, Args... args)
  {
    cont( f(args...) );
  }
};

template<>
struct Continuation<void>
{
  typedef std::function<void()> type;
  template<typename func, typename... Args>
  static void Apply( type const& cont, func&& f, Args... args)
  {
    f(args...);
    cont();
  }
};

如果传入类型是 void 或非 void 类型,它允许您统一将延续应用于函数的执行。

但是,我会问“你为什么要这样做”?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C++ 中使用“void”模板参数 的相关文章

随机推荐