是否可以在不编写自定义特征类的情况下对类型进行模式匹配?

Wyz*_*a-- 7 c++ templates template-meta-programming c++17

由于C ++ 20概念尚未标准化,因此我将其static_assert用作临时概念检查,以在不满足类型要求的情况下提供有用的错误消息。在这种情况下,我有一个函数要求在获取结果类型之前可调用该类型:

template <typename F, typename... Args>
void example() {
  static_assert(std::is_invocable_v<F, Args...>, "Function must be callable");
  using R = std::invoke_result_t<F, Args...>;

  // ...
}
Run Code Online (Sandbox Code Playgroud)

另外,我要求可调用对象的结果必须为std::optional,但我不知道可选对象将保留哪种类型,因此我需要从中获取该类型:

using R = // ...
using T = typename R::value_type;  // std::optional defines a value_type
Run Code Online (Sandbox Code Playgroud)

但是,如果type R没有,则失败value_type,例如,如果不是std::optional预期的。static_assert如果断言失败,我想先进行检查,并给出另一个不错的错误消息。

我可以使用来检查确切的类型std::is_same_v,但在这种情况下,我不知道确切的类型。我想检查是否R是的某些实例std::optional,而不指定它必须是哪个实例。

一种实现方法是使用助手特性:

template <typename T>
struct is_optional { static constexpr bool value = false; };

template <typename T>
struct is_optional<std::optional<T>> { static constexpr bool value = true; };

template <typename T>
constexpr bool is_optional_v = is_optional<T>::value;
Run Code Online (Sandbox Code Playgroud)

…然后我可以写:

static_assert(is_optional_v<R>, "Function's result must be an optional");
Run Code Online (Sandbox Code Playgroud)

那行得通,但是用一个辅助特性来污染我的命名空间只是为了一次这样的检查似乎有点尴尬。我不希望is_optional别的地方需要其他东西,尽管我可以想象可能最终会出现其他一次性特征,例如is_variantis_pair也是如此。

所以我想知道:是否有更简洁的方法? 是否可以对实例进行模式匹配std::optional而不必定义is_optional特征及其部分专业化?

Wyz*_*a-- 5

根据几位受访者的建议,我做了一个可重用的特性:

template <typename T, template <typename...> typename Tpl>
struct is_template_instance : std::false_type { };

template <template <typename...> typename Tpl, typename... Args>
struct is_template_instance<Tpl<Args...>, Tpl> : std::true_type { };

template <typename T, template <typename...> typename Tpl>
constexpr bool is_template_instance_v = is_template_instance<T, Tpl>::value;
Run Code Online (Sandbox Code Playgroud)

……这样我就可以写:

static_assert(is_template_instance_v<R, std::optional>, "Function's result must be an optional");
Run Code Online (Sandbox Code Playgroud)

这与is_optionaltrait 的行和声明一样多,但不再是一次性的;我可以使用相同的特征来检查其他类型的模板(如变体和对)。所以现在它感觉像是对我的项目的一个有用的补充,而不是一个 kluge。