如何编写一个概念,用于检查std::tuple中所有类型的内部类型?

huangapple go评论78阅读模式
英文:

How to write a concept that checks for an inner type in all the types of a std::tuple?

问题

我预期会出现概念不满足的错误,因为type_1::innertype_2::inner具有不同的类型,但是没有报告任何错误。

英文:

Continuing with my studies on C++ 20 concepts, I am trying to write a concept that would assure that every type in a std::tuple has inner type defined with a specific name, and that all the inners have the same type.

I tried this:

#include <concepts>
#include <string>
#include <tuple>

template <typename t>
concept type_model = requires(t p_t) {
  typename t::inner;
};

template <typename t, typename u>
concept same_inner = requires(t p_t, u p_u) {
  std::is_same_v<typename t::inner, typename u::inner>;
};

template <typename t, typename... t_type_model>
concept container_model = requires(t p_t) {

  requires((same_inner<t_type_model,
                       std::tuple_element_t<0, std::tuple<t_type_model...>>> &&
            ...));
};

struct type_1 {
  using inner = int;
};

struct type_2 {
  using inner = std::string;
};

template <type_model... t_type_models> struct container {};

template <type_model... t_type_model>
void f(container_model<t_type_model...> auto) {}

using containers_X = container<type_1, type_2>;

int main() {

  containers_X _x;

  f(_x);

  return 0;
}

I expected an error of concept not satisfied because type_1::inner and type_2::inner have different types, but no errors were reported.

答案1

得分: 2

Your concept same_inner have no effect and can be compiled with any types.

You should use same_as concept in your
same_inner concept restriction, instead of is_same, which always compiles successfully and you cound fetch the result from.

template<typename T, typename U>
concept same_inner = same_as<typename T::inner, typename U::inner>;

This may fix the problem.

See here for detailed informations.

英文:

Your concept same_inner have no effect and can be compiled with any types.

You should use same_as concept in your
same_inner concept restriction, instead of is_same, which always compiles successfully and you cound fetch the result from.

template<typename T, typename U>
concept same_inner = same_as<typename T::inner, typename U::inner>;

This may fix the problem.

See here for detailed informations.

答案2

得分: 2

Here is the translated code:

模板 <typename t, typename... t_type_model>
概念 container_model = 需要(t p_t) {

  需要((same_inner<t_type_model,
                       std::tuple_element_t<0, std::tuple<t_type_model...>>> &&
            ...));
};

这段代码实际上没有测试第二个需要子句中的条件。

正确的形式是
```c++
模板 <typename t, typename u>
概念 same_inner = std::is_same_v<typename t::inner, typename u::inner>;

或者,

模板 <typename t, typename u>
概念 same_inner = 需要 (t i, u j) {
    需要 (std::same_as<typename t::inner, typename u::inner>);
};

这曾经让我感到困惑。

更新

container_model 概念

模板 <typename t, typename... t_type_model>
概念 container_model = 需要(t p_t) {

  需要((same_inner<t_type_model,
                       std::tuple_element_t<0, std::tuple<t_type_model...>>> &&
            ...));
};

需要像这样

模板 <typename t, typename... t_type_model>
概念 container_model = (same_inner<t, t_type_model> && ...);

在这一点上,以下断言应该成立:

static_assert(not same_inner<type_1, type_2>);
static_assert(not container_model<type_1, type_2>);

当调用函数 f 时,它会传递 container<type_1, type_2>,它符合 container_model,因为它被转换为 container_model<container<type_t, type_2>>,返回 true

一种可能的修复方法是将 f 更改为以下方式之一:

模板 <type_model... t_type_model>
void f(container_model<container<t_type_model...>> auto) {}

摘要

为了明确,以下是带有更改的所有代码,此代码无法编译,因为未满足 container_model 约束。

#include <concepts>
#include <string>
#include <tuple>

模板 <typename t>
概念 type_model = 需要(t p_t) {
  typename t::inner;
};

模板 <typename t, typename u>
概念 same_inner = std::is_same_v<typename std::decay_t<t>::inner,
                                    typename std::decay_t<u>::inner>;

模板 <typename t, typename... t_type_model>
概念 container_model = (same_inner<t, t_type_model> && ...);

结构体 type_1 {
  using inner = int;
};

结构体 type_2 {
  using inner = std::string;
};

模板 <type_model... t_type_models> 结构体 container {};

模板 <type_model... t_type_model>
void f(container_model<container<t_type_model...>> auto) {}

使用 containers_X = container<type_1, type_2>;

static_assert(not same_inner<type_1, type_2>);
static_assert(not container_model<type_1, type_2>);

int main() {

  containers_X _x;

  f(_x);

  返回 0;
}

新的更新

以前的更新在最好情况下是不完整的。以下是我认为可以实现所需概念的最新代码。

示例代码

#include <concepts>
#include <string>
#include <tuple>

// 类型 T 是否具有名为 `inner` 的内部类型。
模板< T>
概念 Inner = 需要(T x) {
    typename T::inner;
};

// T 和 U 是否具有相同的内部类型。
模板< T,  U>
概念 SameInner = Inner<T>  Inner<U>  std::is_same_v<typename T::inner, typename U::inner>;

// 用于检查所有模板参数是否满足 Inner 概念以及所有配对是否满足 SameInner 的辅助程序。
模板<typename>
结构体 inner_container_impl : std::false_type {};

模板<模板<typename...>  Tp, Inner T>
结构体 inner_container_impl<Tp<T>> {
    static constexpr bool value = true;
};

模板<模板<typename...>  Tp, Inner T, Inner... Ts>
结构体 inner_container_impl<Tp<T, Ts...>> {
    static constexpr bool value = (SameInner<T, Ts>  ...);
};

// 该概念只是使用辅助程序。
模板< T>
概念 InnerContainer = inner_container_impl<T>::value;

// 测试类型。
结构体 type_1 {
    using inner = int;
};

结构体 type_2 {
    using inner = std::string;
};

结构体 type_3 {
    using inner = int;
};

模板<Inner... Ts> 结构体 container {};

void f(InnerContainer auto) {}

使用 containers_X = std::tuple<type_1, type_2>;
使用 containers_Y = std::tuple<type_1, type_3>;

static_assert(not SameInner<type_1, type_2>);
static_assert(not InnerContainer<std::tuple<type_1, type_2>>);
static_assert(not InnerContainer<containers_X>);

int main() {

    containers_X _x;
    f(_x);

    containers_Y _y;
    f(_y);

  返回 0;
}

输出

/work/so/scratch/src/p4.cpp:64:5: 错误: 没有匹配

<details>
<summary>英文:</summary>

This code,
```c++
template &lt;typename t, typename... t_type_model&gt;
concept container_model = requires(t p_t) {

  requires((same_inner&lt;t_type_model,
                       std::tuple_element_t&lt;0, std::tuple&lt;t_type_model...&gt;&gt;&gt; &amp;&amp;
            ...));
};

does not actually test the condition within the second requires clause.

The correct formulation is

template &lt;typename t, typename u&gt;
concept same_inner = std::is_same_v&lt;typename t::inner, typename u::inner&gt;;

or,

template &lt;typename t, typename u&gt;
concept same_inner = requires (t i, u j) {
    requires (std::same_as&lt;typename t::inner, typename u::inner&gt;);
};

This has tripped me up in the past.

Update

The container_model concept

template &lt;typename t, typename... t_type_model&gt;
concept container_model = requires(t p_t) {

  requires((same_inner&lt;t_type_model,
                       std::tuple_element_t&lt;0, std::tuple&lt;t_type_model...&gt;&gt;&gt; &amp;&amp;
            ...));
};

need to be something like

template &lt;typename t, typename... t_type_model&gt;
concept container_model = (same_inner&lt;t, t_type_model&gt; &amp;&amp; ...);

At this point, the following assertions should hold:

static_assert(not same_inner&lt;type_1, type_2&gt;);
static_assert(not container_model&lt;type_1, type_2&gt;);

When the function f is invoked, it is passed container&lt;type_1, type_2&gt; which qualifies as a container_model because it gets translated to container_model&lt;container&lt;type_t, type_2&gt;&gt; which returns true.

One possible fix is to change f to something like

template &lt;type_model... t_type_model&gt;
void f(container_model&lt;container&lt;t_type_model...&gt;&gt; auto) {}

Summary

Just to be clear, here is all the code with changes and this code fails to compile because the container_model constraints are not satisfied.

#include &lt;concepts&gt;
#include &lt;string&gt;
#include &lt;tuple&gt;

template &lt;typename t&gt;
concept type_model = requires(t p_t) {
  typename t::inner;
};

template &lt;typename t, typename u&gt;
concept same_inner = std::is_same_v&lt;typename std::decay_t&lt;t&gt;::inner,
                                    typename std::decay_t&lt;u&gt;::inner&gt;;

template &lt;typename t, typename... t_type_model&gt;
concept container_model = (same_inner&lt;t, t_type_model&gt; &amp;&amp; ...);

struct type_1 {
  using inner = int;
};

struct type_2 {
  using inner = std::string;
};

template &lt;type_model... t_type_models&gt; struct container {};

template &lt;type_model... t_type_model&gt;
void f(container_model&lt;container&lt;t_type_model...&gt;&gt; auto) {}

using containers_X = container&lt;type_1, type_2&gt;;

static_assert(not same_inner&lt;type_1, type_2&gt;);
static_assert(not container_model&lt;type_1, type_2&gt;);

int main() {

  containers_X _x;

  f(_x);

  return 0;
}

New Update

The previous update was incomplete at best. Here is the latest code which I believe enforces the desired concepts.

Sample Code

#include &lt;concepts&gt;
#include &lt;string&gt;
#include &lt;tuple&gt;

// Does T have an inner type named `inner`.
template&lt;class T&gt;
concept Inner = requires(T x) {
    typename T::inner;
};

// Do T and U have same inner type.
template&lt;class T, class U&gt;
concept SameInner = Inner&lt;T&gt; and Inner&lt;U&gt; and std::is_same_v&lt;typename T::inner, typename U::inner&gt;;

// Helper for checking that all template parameters satisfy Inner
// concept and all pairs satisfy SameInner.
template&lt;typename&gt;
struct inner_container_impl : std::false_type {};

template&lt;template&lt;typename...&gt; class Tp, Inner T&gt;
struct inner_container_impl&lt;Tp&lt;T&gt;&gt; {
    static constexpr bool value = true;
};

template&lt;template&lt;typename...&gt; class Tp, Inner T, Inner... Ts&gt;
struct inner_container_impl&lt;Tp&lt;T, Ts...&gt;&gt; {
    static constexpr bool value = (SameInner&lt;T, Ts&gt; and ...);
};

// The concept just use the helper.
template&lt;class T&gt;
concept InnerContainer = inner_container_impl&lt;T&gt;::value;

// Test types.
struct type_1 {
    using inner = int;
};

struct type_2 {
    using inner = std::string;
};

struct type_3 {
    using inner = int;
};

template&lt;Inner... Ts&gt; struct container {};

void f(InnerContainer auto) {}

using containers_X = std::tuple&lt;type_1, type_2&gt;;
using containers_Y = std::tuple&lt;type_1, type_3&gt;;

static_assert(not SameInner&lt;type_1, type_2&gt;);
static_assert(not InnerContainer&lt;std::tuple&lt;type_1, type_2&gt;&gt;);
static_assert(not InnerContainer&lt;containers_X&gt;);

int main() {

    containers_X _x;
    f(_x);

    containers_Y _y;
    f(_y);

  return 0;
}

Output

/work/so/scratch/src/p4.cpp:64:5: error: no matching
function for call to &#39;f&#39;
f(_x);
^
/work/so/scratch/src/p4.cpp:52:6: note: candidate
template ignored: constraints not satisfied [with auto:1 = std::tuple&lt;type_1,
type_2&gt;]
void f(InnerContainer auto) {}
^
/work/so/scratch/src/p4.cpp:52:8: note: because
&#39;std::tuple&lt;type_1, type_2&gt;&#39; does not satisfy &#39;InnerContainer&#39;
void f(InnerContainer auto) {}
^
/work/so/scratch/src/p4.cpp:35:26: note: because
&#39;inner_container_impl&lt;tuple&lt;type_1, type_2&gt; &gt;::value&#39; evaluated to false
concept InnerContainer = inner_container_impl&lt;T&gt;::value;
^
1 error generated.

答案3

得分: 0

除了@RandomBits的实现之外,我认为我找到了另一个实现:

#include <concepts>
#include <iomanip>
#include <iostream>
#include <string>
#include <tuple>

template <typename t>
concept has_inner = requires(t p_t) {
  typename t::inner;
};

template <has_inner t_1, has_inner t_2> struct same_inner {
  static constexpr bool yes{
      std::is_same_v<typename t_1::inner, typename t_2::inner>};
};

template <typename t_tuple, size_t t_idx = std::tuple_size_v<t_tuple> - 1>
struct check_if_all_has_inner {
  static constexpr bool yes{
      same_inner<typename std::tuple_element_t<t_idx, t_tuple>,
                 typename std::tuple_element_t<t_idx - 1, t_tuple>>::yes &&
      check_if_all_has_inner<t_tuple, t_idx - 1>::yes};
};

template <typename t_tuple> struct check_if_all_has_inner<t_tuple, 0> {
  static constexpr bool yes{true};
};

template <typename t_tuple>
concept container_model = (std::tuple_size_v<t_tuple> > 0) &&
                          (check_if_all_has_inner<t_tuple>::yes);

struct type_1 {
  using inner = int;
};

struct type_2 {
  using inner = std::string;
};

struct type_3 {
  using inner = std::string;
};

struct type_4 {};

void f(container_model auto) {}

int main() {

  /// ERROR 1 if code below uncommented
  //  f(std::tuple<type_1, type_2>{});

  f(std::tuple<type_2, type_3>{});

  {
    std::cout << std::boolalpha
              << check_if_all_has_inner<std::tuple<type_1, type_2>>::yes
              << std::endl;
  }

  {
    std::cout << std::boolalpha
              << check_if_all_has_inner<std::tuple<type_3, type_2>>::yes
              << std::endl;
  }

  ///   ERROR 2 if code below uncommented
  //  {
  //    std::cout << std::boolalpha
  //              << check_if_all_has_inner<std::tuple<type_3, type_2,
  //              type_4>>::yes
  //              << std::endl;
  //  }

  return 0;
}

其中ERROR 1是:

main.cpp:52:3: No matching function for call to 'f'
main.cpp:47:6: candidate template ignored: constraints not satisfied [with auto:1 = std::tuple<type_1, type_2>] main.cpp:47:8: because 'std::tuple<type_1, type_2>' does not satisfy 'container_model' main.cpp:31:28: because 'check_if_all_has_inner<tuple<type_1, type_2> >::yes' evaluated to false

ERROR 2是:

main.cpp:71:78: In instantiation of static data member 'check_if_all_has_inner<std::tuple<type_3, type_2, type_4>, 2>::yes' requested here main.cpp:20:7: In instantiation of static data member 'check_if_all_has_inner<std::tuple<type_3, type_2, type_4>, 2>::yes' requested here

main.cpp:20:7: Constraints not satisfied for class template 'same_inner' [with t_1 = type_4, t_2 = type_2] main.cpp:71:78: in instantiation of static data member 'check_if_all_has_inner<std::tuple<type_3, type_2, type_4>, 2>::yes' requested here main.cpp:12:11: because 'type_4' does not satisfy 'has_inner' main.cpp:9:15: because 'typename t::inner' would be invalid: no type named 'inner' in 'type_4'

如果需要进一步解释或翻译其他部分,请告诉我。

英文:

Besides @RandomBits implementation, I believe I found another one:

#include &lt;concepts&gt;
#include &lt;iomanip&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;tuple&gt;
template &lt;typename t&gt;
concept has_inner = requires(t p_t) {
typename t::inner;
};
template &lt;has_inner t_1, has_inner t_2&gt; struct same_inner {
static constexpr bool yes{
std::is_same_v&lt;typename t_1::inner, typename t_2::inner&gt;};
};
template &lt;typename t_tuple, size_t t_idx = std::tuple_size_v&lt;t_tuple&gt; - 1&gt;
struct check_if_all_has_inner {
static constexpr bool yes{
same_inner&lt;typename std::tuple_element_t&lt;t_idx, t_tuple&gt;,
typename std::tuple_element_t&lt;t_idx - 1, t_tuple&gt;&gt;::yes &amp;&amp;
check_if_all_has_inner&lt;t_tuple, t_idx - 1&gt;::yes};
};
template &lt;typename t_tuple&gt; struct check_if_all_has_inner&lt;t_tuple, 0&gt; {
static constexpr bool yes{true};
};
template &lt;typename t_tuple&gt;
concept container_model = (std::tuple_size_v&lt;t_tuple&gt; &gt; 0) &amp;&amp;
(check_if_all_has_inner&lt;t_tuple&gt;::yes);
struct type_1 {
using inner = int;
};
struct type_2 {
using inner = std::string;
};
struct type_3 {
using inner = std::string;
};
struct type_4 {};
void f(container_model auto) {}
int main() {
/// ERROR 1 if code below uncommented
//  f(std::tuple&lt;type_1, type_2&gt;{});
f(std::tuple&lt;type_2, type_3&gt;{});
{
std::cout &lt;&lt; std::boolalpha
&lt;&lt; check_if_all_has_inner&lt;std::tuple&lt;type_1, type_2&gt;&gt;::yes
&lt;&lt; std::endl;
}
{
std::cout &lt;&lt; std::boolalpha
&lt;&lt; check_if_all_has_inner&lt;std::tuple&lt;type_3, type_2&gt;&gt;::yes
&lt;&lt; std::endl;
}
///   ERROR 2 if code below uncommented
//  {
//    std::cout &lt;&lt; std::boolalpha
//              &lt;&lt; check_if_all_has_inner&lt;std::tuple&lt;type_3, type_2,
//              type_4&gt;&gt;::yes
//              &lt;&lt; std::endl;
//  }
return 0;
}

Where ERROR 1 is

main.cpp:52:3: No matching function for call to &#39;f&#39;
main.cpp:47:6: candidate template ignored: constraints not satisfied [with
auto:1 = std::tuple&lt;type_1, type_2&gt;] main.cpp:47:8: because &#39;std::tuple&lt;type_1,
type_2&gt;&#39; does not satisfy &#39;container_model&#39; main.cpp:31:28: because
&#39;check_if_all_has_inner&lt;tuple&lt;type_1, type_2&gt; &gt;::yes&#39; evaluated to false

and ERROR 2 is

main.cpp:71:78: In instantiation of static data member
&#39;check_if_all_has_inner&lt;std::tuple&lt;type_3, type_2, type_4&gt;, 2&gt;::yes&#39; requested
here main.cpp:20:7: In instantiation of static data member
&#39;check_if_all_has_inner&lt;std::tuple&lt;type_3, type_2, type_4&gt;, 2&gt;::yes&#39; requested
here
main.cpp:20:7: Constraints not satisfied for class template &#39;same_inner&#39; [with
t_1 = type_4, t_2 = type_2] main.cpp:71:78: in instantiation of static data
member &#39;check_if_all_has_inner&lt;std::tuple&lt;type_3, type_2, type_4&gt;, 2&gt;::yes&#39;
requested here main.cpp:12:11: because &#39;type_4&#39; does not satisfy &#39;has_inner&#39;
main.cpp:9:15: because &#39;typename t::inner&#39; would be invalid: no type named
&#39;inner&#39; in &#39;type_4&#39;

答案4

得分: 0

Sure, here is the translated code portion:

[RandomBits][1],基于[这个][2]主题,我想我提出了另一种实现:

#include <concepts>
#include <iomanip>
#include <iostream>
#include <string>
#include <tuple>
#include <type_traits>

// 检查类型是否为std::tuple
template <class t_tuple, std::size_t t_idx>
concept has_tuple_element = requires(t_tuple t) {
  typename std::tuple_element_t<t_idx, std::remove_const_t<t_tuple>>;
  {
    get<t_idx>(t)
  } -> std::convertible_to<const std::tuple_element_t<t_idx, t_tuple> &>;
};

template <class t_tuple>
concept tuple_like = !std::is_reference_v<t_tuple> && requires(t_tuple t) {
  typename std::tuple_size<t_tuple>::type;
  requires std::derived_from<
      std::tuple_size<t_tuple>,
      std::integral_constant<std::size_t, std::tuple_size_v<t_tuple>>>;
}
&& []<std::size_t... t_idx>(std::index_sequence<t_idx...>) {
  return (has_tuple_element<t_tuple, t_idx> && ...);
}
(std::make_index_sequence<std::tuple_size_v<t_tuple>>());

// 检查元组中索引位置的类型是否具有'inner'类型,如果前一个索引位置也具有'inner'类型,且两个'inner'类型相同
template <size_t t_idx, typename t_tuple> struct same_inner {
  static constexpr bool yes{
      std::is_same_v<typename std::tuple_element_t<t_idx, t_tuple>::inner,
                     typename std::tuple_element_t<t_idx - 1, t_tuple>::inner>};
};

template <typename t_tuple> struct same_inner<0, t_tuple> {
  static constexpr bool yes{true};
};

// std::tuple,其中所有类型具有'inner'类型
template <typename t_tuple>
concept container_model = (tuple_like<t_tuple>)&&[]<std::size_t... t_idx>(
    std::index_sequence<t_idx...>) {
  return (same_inner<t_idx, t_tuple>::yes && ...);
}
(std::make_index_sequence<std::tuple_size_v<t_tuple>>());

// 示例
struct type_1 {
  using inner = int;
};

struct type_2 {
  using inner = std::string;
};

struct type_3 {
  using inner = std::string;
};

struct type_4 {};

// 处理所有类型具有'inner'类型的std::tuple的函数
void f(container_model auto) {}

int main() {

  f(std::tuple<type_2, type_3>{});

  /// 如果取消下面的代码的注释,将会出错
  //  f(std::tuple<type_1, type_2>{});

  /// 如果取消下面的代码的注释,将会出错
  //   f(std::tuple<type_2, type_4>{});

  /// 如果取消下面的代码的注释,将会出错
  //  f(int{3});

  return 0;
}

<details>
<summary>英文:</summary>
[RandomBits][1], based on [this][2] topic, I think I came up with another implentation:
#include &lt;concepts&gt;
#include &lt;iomanip&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;tuple&gt;
#include &lt;type_traits&gt;
// checking if a type is a std::tuple
template &lt;class t_tuple, std::size_t t_idx&gt;
concept has_tuple_element = requires(t_tuple t) {
typename std::tuple_element_t&lt;t_idx, std::remove_const_t&lt;t_tuple&gt;&gt;;
{
get&lt;t_idx&gt;(t)
} -&gt; std::convertible_to&lt;const std::tuple_element_t&lt;t_idx, t_tuple&gt; &amp;&gt;;
};
template &lt;class t_tuple&gt;
concept tuple_like = !std::is_reference_v&lt;t_tuple&gt; &amp;&amp; requires(t_tuple t) {
typename std::tuple_size&lt;t_tuple&gt;::type;
requires std::derived_from&lt;
std::tuple_size&lt;t_tuple&gt;,
std::integral_constant&lt;std::size_t, std::tuple_size_v&lt;t_tuple&gt;&gt;&gt;;
}
&amp;&amp;[]&lt;std::size_t... t_idx&gt;(std::index_sequence&lt;t_idx...&gt;) {
return (has_tuple_element&lt;t_tuple, t_idx&gt; &amp;&amp; ...);
}
(std::make_index_sequence&lt;std::tuple_size_v&lt;t_tuple&gt;&gt;());
// checking if a type in a index of a tuple has &#39;inner&#39; type, if the index
// before it has a &#39;inner&#39; type, and if both &#39;inner&#39; types are identical
template &lt;size_t t_idx, typename t_tuple&gt; struct same_inner {
static constexpr bool yes{
std::is_same_v&lt;typename std::tuple_element_t&lt;t_idx, t_tuple&gt;::inner,
typename std::tuple_element_t&lt;t_idx - 1, t_tuple&gt;::inner&gt;};
};
template &lt;typename t_tuple&gt; struct same_inner&lt;0, t_tuple&gt; {
static constexpr bool yes{true};
};
// std::tuple where all the types have a &#39;inner&#39; type
template &lt;typename t_tuple&gt;
concept container_model = (tuple_like&lt;t_tuple&gt;)&amp;&amp;[]&lt;std::size_t... t_idx&gt;(
std::index_sequence&lt;t_idx...&gt;) {
return (same_inner&lt;t_idx, t_tuple&gt;::yes &amp;&amp; ...);
}
(std::make_index_sequence&lt;std::tuple_size_v&lt;t_tuple&gt;&gt;());
// examples
struct type_1 {
using inner = int;
};
struct type_2 {
using inner = std::string;
};
struct type_3 {
using inner = std::string;
};
struct type_4 {};
// function that will handle a std::tuple where all the types have a &#39;inner&#39;
// type
void f(container_model auto) {}
int main() {
f(std::tuple&lt;type_2, type_3&gt;{});
/// ERROR if code below uncommented
//  f(std::tuple&lt;type_1, type_2&gt;{});
/// ERROR if code below uncommented
//   f(std::tuple&lt;type_2, type_4&gt;{});
/// ERROR if code below uncommented
//  f(int{3});
return 0;
}
[1]: https://stackoverflow.com/users/1202808/randombits
[2]: https://stackoverflow.com/questions/68443804/c20-concept-to-check-tuple-like-types
</details>

huangapple
  • 本文由 发表于 2023年5月11日 10:54:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76223849.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定