一个限制返回值的思路

问题

限制函数的返回值为 task<T> task是一个模板类。

分析

如果仅是task的,那不管是sfinae还是concepts都能轻松办到,但要限制的类型本身就是个范型那就得找另外的办法了,比如 source_location,但这个需要C++20的支持,之前可以使用编译器自带的宏解决一下,下面使用source_location实现个

实现

#include <string_view>
#if __has_include(<experimental/source_location>)
#include <experimental/source_location>
using sl = std::experimental::source_location;
#elif __has_include(<source_location>)
#include <source_location>
using sl = std::source_location;
#else
#error "not support"
#endif

template<typename T> struct task {};

template<typename F, typename... Args>
concept my_callable = requires(F&& f, Args&&... args)
{
  {std::forward<F>(f)(std::forward<Args>(args)...)};
};

template<typename F, typename... Args> requires my_callable<F, Args...>
constexpr auto has_return_signature(std::string_view target, F&&, Args&&...)
{
  std::string_view name{sl::current().function_name()};
  auto beg = name.find("<")+1;
  auto end = name.find(" (");

  return name.substr(beg, end-beg) == target;
}

task<int> foo() { return {}; }
int bar() { return 0; }
void mo() {}

int main()
{
  static_assert(has_return_signature("task<int>", foo));
  static_assert(has_return_signature("int", bar));
  static_assert(has_return_signature("void", mo));
  static_assert(has_return_signature("task", foo));
}

编译一下:

x.cc: In function ‘int main()’:
x.cc:39:37: error: static assertion failed
   39 |   static_assert(has_return_signature("task", foo));

还行吧,告辞。