如何将requires子句和一个参数包相互关联的参数提取成一个概念?
How to extract requires clause with a parameter pack whose parameters are related to each other into a concept?
我有这么一套玩具功能:
template <typename... Args>
requires std::conjunction_v<std::is_convertible<Args, int>...>
void test(Args...) { std::cout << "int"; }
template <typename... Args>
requires std::conjunction_v<
std::disjunction<std::is_convertible<Args, int>,
std::is_convertible<Args, std::string>>...> &&
std::disjunction_v<std::is_convertible<Args, std::string>...>
void test(Args...) { std::cout << "istring"; }
当我使用所有可转换为 int 且不可转换为 std::string 的参数时,将调用第一个函数,例如:test(1, 2L, 3.0, 4UL)
.
如果至少有一个参数可以转换为 std::string,并且如果所有参数都可以转换为 int 或 std::string,则将调用第二个函数,例如 test(1, 2L, "Hello", 4UL)
。
和我预期的一样。
但是,当我将第二个函数编码为以下两种样式时,它不起作用。 arguments的概念一一检查,1, 2L, 4UL
不是Istring
.
template <typename... Args>
concept Istring = std::conjunction_v<
std::disjunction<std::is_convertible<Args, int>,
std::is_convertible<Args, std::string>>...> &&
std::disjunction_v<std::is_convertible<Args, std::string>...>;
void test(Istring auto...) { std::cout << "istring"; }
template <typename... Args>
concept Istring = std::conjunction_v<
std::disjunction<std::is_convertible<Args, int>,
std::is_convertible<Args, std::string>>...> &&
std::disjunction_v<std::is_convertible<Args, std::string>...>;
template <IString... Args>
void test(Args...) { std::cout << "istring"; }
我想知道是否有提取概念的方法。
在这种情况下不需要使用 std::conjunction
和 std::disjunction
,因为它会使代码冗长且难以阅读。使用倍表达式会更直观。
template <typename... Args>
requires (std::is_convertible_v<Args, int> && ...)
void test(Args...) { std::cout << "int\n"; }
template <typename... Args>
concept Istring =
((std::is_convertible_v<Args, int> ||
std::is_convertible_v<Args, std::string>) && ...) &&
(std::is_convertible_v<Args, std::string> || ... );
template <Istring... Args>
void test(Args...) { std::cout << "istring\n"; }
在上面的例子中,Istring
只会约束一个单个参数,而不是参数包,即检查是否每个 参数满足以下退化约束:
template <typename T>
concept Istring =
(std::is_convertible_v<T, int> || std::is_convertible_v<T, std::string>) &&
std::is_convertible_v<T, std::string>;
您应该使用 requires
子句来检查所有参数,例如:
template <typename... Args>
requires Istring<Args...>
void test(Args...) { std::cout << "istring\n"; }
我有这么一套玩具功能:
template <typename... Args>
requires std::conjunction_v<std::is_convertible<Args, int>...>
void test(Args...) { std::cout << "int"; }
template <typename... Args>
requires std::conjunction_v<
std::disjunction<std::is_convertible<Args, int>,
std::is_convertible<Args, std::string>>...> &&
std::disjunction_v<std::is_convertible<Args, std::string>...>
void test(Args...) { std::cout << "istring"; }
当我使用所有可转换为 int 且不可转换为 std::string 的参数时,将调用第一个函数,例如:test(1, 2L, 3.0, 4UL)
.
如果至少有一个参数可以转换为 std::string,并且如果所有参数都可以转换为 int 或 std::string,则将调用第二个函数,例如 test(1, 2L, "Hello", 4UL)
。
和我预期的一样。
但是,当我将第二个函数编码为以下两种样式时,它不起作用。 arguments的概念一一检查,1, 2L, 4UL
不是Istring
.
template <typename... Args>
concept Istring = std::conjunction_v<
std::disjunction<std::is_convertible<Args, int>,
std::is_convertible<Args, std::string>>...> &&
std::disjunction_v<std::is_convertible<Args, std::string>...>;
void test(Istring auto...) { std::cout << "istring"; }
template <typename... Args>
concept Istring = std::conjunction_v<
std::disjunction<std::is_convertible<Args, int>,
std::is_convertible<Args, std::string>>...> &&
std::disjunction_v<std::is_convertible<Args, std::string>...>;
template <IString... Args>
void test(Args...) { std::cout << "istring"; }
我想知道是否有提取概念的方法。
在这种情况下不需要使用 std::conjunction
和 std::disjunction
,因为它会使代码冗长且难以阅读。使用倍表达式会更直观。
template <typename... Args>
requires (std::is_convertible_v<Args, int> && ...)
void test(Args...) { std::cout << "int\n"; }
template <typename... Args>
concept Istring =
((std::is_convertible_v<Args, int> ||
std::is_convertible_v<Args, std::string>) && ...) &&
(std::is_convertible_v<Args, std::string> || ... );
template <Istring... Args>
void test(Args...) { std::cout << "istring\n"; }
在上面的例子中,Istring
只会约束一个单个参数,而不是参数包,即检查是否每个 参数满足以下退化约束:
template <typename T>
concept Istring =
(std::is_convertible_v<T, int> || std::is_convertible_v<T, std::string>) &&
std::is_convertible_v<T, std::string>;
您应该使用 requires
子句来检查所有参数,例如:
template <typename... Args>
requires Istring<Args...>
void test(Args...) { std::cout << "istring\n"; }