部分专用模板作为模板参数
partial specialised template as template argument
举例来说,我有一个函数 foo()
采用参数包 Ts
。但是,如果恰好有一种类型满足 std::is_integral
的要求,则该函数应该只接受参数包 Ts
。我编写的以下代码完全符合预期。
#include <type_traits>
template <template <typename> typename predicate, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<Ts>::value ? 1 : 0) + ...);
// this method only compiles if exactly one of the given template arguments is of an integral type
template <typename... Ts>
void foo() requires (count_if<std::is_integral, Ts...> == 1) {}
int main()
{
foo<int, double, float>(); //this compiles
//foo<int, long, float>(); //this doesn't, as it should
}
但是,假设函数 foo()
正在通过模板类型 T
的参数扩展,如下所示:
#include <type_traits>
template <template <typename> typename predicate, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<Ts>::value ? 1 : 0) + ...);
// this method only compiles if one of the given template arguments is of an integral type
template <typename T, typename... Ts>
void foo(T) requires (count_if<std::is_integral, Ts...> == 1) {}
int main()
{
foo<double, int, double, float>(double{}); //this compiles
foo<int, int, double, float>(int{}); //this compiles
//foo<double, int, long, float>(double{}); //this doesn't, as it should
}
现在回答我的问题:是否有可能使我提供给我的 count_if
函数的谓词依赖于我的函数 foo()
的模板参数 T
?
例如,我可以检查以下内容:
#include <type_traits>
template <template <typename> typename predicate, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<Ts>::value ? 1 : 0) + ...);
template <typename T, typename... Ts>
void foo(T) requires (count_if<std::is_same<T, ?????> , Ts...> == 1) {}
int main()
{
foo<double, int, double, float>(double{}); //this should compile, as there is exactly one type in parameter pack of type double
foo<int, int, double, float>(int{}); //this should compile, as there is exactly one type in parameter pack of type int
//foo<int, double, float>(); //this shouldn't compile, as there is no int in parameter pack
//foo<double, double, double>(); //this shouldn't compile, as there are two doubles in paramter pack
}
这有可能吗?我尝试在函数体内使用 static_assert()
来检查它,但我无法在其中定义模板结构,我需要它,所以我可以像这样编写自己的谓词,例如:
template <typename T, typename... Ts>
void foo(T)
{
template <typename U>
struct custom_predicate
{
static constexpr bool value = std::is_same<T, U>::value;
};
static_assert(count_if<custom_predicate, Ts...> == 1);
}
但正如我所说,这是不可能的,因为我无法在函数体内定义模板结构。
有人有想法吗?
我觉得你在找
template <template <typename, typename> typename predicate, typename T, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<T, Ts>::value ? 1 : 0) + ...);
template <typename T, typename... Ts>
void foo(T) requires (count_if<std::is_same, T, Ts...> == 1) {}
但是,这样一来,您就必须更改 count_if
要求。
如果您想要(正如您在 static_assert()
示例中尝试的那样)生成特定 is_same
修复第一种类型的方法,您可以编写类似于 custom_predicate
但在外部的内容函数。
例如
template <template <typename> typename predicate, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<Ts>::value ? 1 : 0) + ...);
template <typename T>
struct my_predicate
{
template <typename U>
using my_is_same = std::is_same<T, U>;
};
template <typename T, typename... Ts>
void foo(T) requires (count_if<my_predicate<T>::template my_is_same, Ts...> == 1)
{ /* ... */ }
或者,为了更灵活(并传递相同的 std::is_same
作为参数)
template <template <typename> typename predicate, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<Ts>::value ? 1 : 0) + ...);
template <template <typename...> class C, typename ... Ts>
struct my_predicate
{
template <typename ... Us>
using my_is_same = C<Ts..., Us...>;
};
template <typename T, typename... Ts>
void foo(T)
requires (count_if<my_predicate<std::is_same, T>::template my_is_same, Ts...> == 1)
{ }
举例来说,我有一个函数 foo()
采用参数包 Ts
。但是,如果恰好有一种类型满足 std::is_integral
的要求,则该函数应该只接受参数包 Ts
。我编写的以下代码完全符合预期。
#include <type_traits>
template <template <typename> typename predicate, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<Ts>::value ? 1 : 0) + ...);
// this method only compiles if exactly one of the given template arguments is of an integral type
template <typename... Ts>
void foo() requires (count_if<std::is_integral, Ts...> == 1) {}
int main()
{
foo<int, double, float>(); //this compiles
//foo<int, long, float>(); //this doesn't, as it should
}
但是,假设函数 foo()
正在通过模板类型 T
的参数扩展,如下所示:
#include <type_traits>
template <template <typename> typename predicate, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<Ts>::value ? 1 : 0) + ...);
// this method only compiles if one of the given template arguments is of an integral type
template <typename T, typename... Ts>
void foo(T) requires (count_if<std::is_integral, Ts...> == 1) {}
int main()
{
foo<double, int, double, float>(double{}); //this compiles
foo<int, int, double, float>(int{}); //this compiles
//foo<double, int, long, float>(double{}); //this doesn't, as it should
}
现在回答我的问题:是否有可能使我提供给我的 count_if
函数的谓词依赖于我的函数 foo()
的模板参数 T
?
例如,我可以检查以下内容:
#include <type_traits>
template <template <typename> typename predicate, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<Ts>::value ? 1 : 0) + ...);
template <typename T, typename... Ts>
void foo(T) requires (count_if<std::is_same<T, ?????> , Ts...> == 1) {}
int main()
{
foo<double, int, double, float>(double{}); //this should compile, as there is exactly one type in parameter pack of type double
foo<int, int, double, float>(int{}); //this should compile, as there is exactly one type in parameter pack of type int
//foo<int, double, float>(); //this shouldn't compile, as there is no int in parameter pack
//foo<double, double, double>(); //this shouldn't compile, as there are two doubles in paramter pack
}
这有可能吗?我尝试在函数体内使用 static_assert()
来检查它,但我无法在其中定义模板结构,我需要它,所以我可以像这样编写自己的谓词,例如:
template <typename T, typename... Ts>
void foo(T)
{
template <typename U>
struct custom_predicate
{
static constexpr bool value = std::is_same<T, U>::value;
};
static_assert(count_if<custom_predicate, Ts...> == 1);
}
但正如我所说,这是不可能的,因为我无法在函数体内定义模板结构。
有人有想法吗?
我觉得你在找
template <template <typename, typename> typename predicate, typename T, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<T, Ts>::value ? 1 : 0) + ...);
template <typename T, typename... Ts>
void foo(T) requires (count_if<std::is_same, T, Ts...> == 1) {}
但是,这样一来,您就必须更改 count_if
要求。
如果您想要(正如您在 static_assert()
示例中尝试的那样)生成特定 is_same
修复第一种类型的方法,您可以编写类似于 custom_predicate
但在外部的内容函数。
例如
template <template <typename> typename predicate, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<Ts>::value ? 1 : 0) + ...);
template <typename T>
struct my_predicate
{
template <typename U>
using my_is_same = std::is_same<T, U>;
};
template <typename T, typename... Ts>
void foo(T) requires (count_if<my_predicate<T>::template my_is_same, Ts...> == 1)
{ /* ... */ }
或者,为了更灵活(并传递相同的 std::is_same
作为参数)
template <template <typename> typename predicate, typename... Ts>
inline constexpr std::size_t count_if = ((predicate<Ts>::value ? 1 : 0) + ...);
template <template <typename...> class C, typename ... Ts>
struct my_predicate
{
template <typename ... Us>
using my_is_same = C<Ts..., Us...>;
};
template <typename T, typename... Ts>
void foo(T)
requires (count_if<my_predicate<std::is_same, T>::template my_is_same, Ts...> == 1)
{ }