具有两个以上参数的可变参数模板函数
Variadic template function with more than two parameters
我有以下示例,其中使用了两个参数 t1 和 t2。
template<typename T>
bool Compare(T t1, T t2)
{
return t1 == t2;
}
template<typename T, typename... Args>
bool Compare(T t1, T t2, Args... args)
{
return (t1 == t2) && Compare(args...);
}
int main(void)
{
Compare(1, 1, "string", "string");
}
函数比较采用相同类型且可以比较的参数对。比较两对,然后递归传递参数包,直到达到最后两个参数。为了停止递归,我使用了没有参数包的比较函数的实现。
我想添加第三个参数 t3,所以函数比较应该是这样的:
template<typename T>
bool Compare(T t1, T t2, T t3)
{
return t1 == t2 == t3;
}
template<typename T, typename... Args>
bool Compare(T t1, T t2, T t3, Args... args)
{
return (t1 == t2 == t3) && Compare(args...);
}
int main(void)
{
Compare(1, 1, 1, "string", "string", "string");
}
我希望这个函数需要三个参数进行比较,然后接下来的三个参数是递归处理的。当我尝试编译此代码时,出现以下错误:
>xxxsource.cpp(4): error C2446: '==': no conversion from 'const char *' to 'int'
1> xxxsource.cpp(4): note: There is no context in which this conversion is possible
1> xxxsource.cpp(10): note: see reference to function template instantiation 'bool Compare<const char*>(T,T,T)' being compiled
1> with
1> [
1> T=const char *
1> ]
1> xxxsource.cpp(15): note: see reference to function template instantiation 'bool Compare<int,const char*,const char*,const char*>(T,T,T,const char *,const char *,const char *)' being compiled
1> with
1> [
1> T=int
1> ]
1>xxxsource.cpp(4): error C2040: '==': 'int' differs in levels of indirection from 'const char *'
如何实现此函数来比较同一类型的三个参数集?
t1 == t2 == t3
这不检查t1
、t2
和t3
是否都相等,它检查t1
是否等于t2
,然后检查结果bool
是否等于t3
。
也许你想要的是(假设合理的相等运算符):
t1 == t2 && t1 == t3
所以你的代码看起来像这样:
template<typename T>
bool Compare(T t1, T t2, T t3)
{
return t1 == t2 && t1 == t3;
}
template<typename T, typename... Args>
bool Compare(T t1, T t2, T t3, Args... args)
{
return t1 == t2 && t1 == t3 && Compare(args...);
}
请注意,使用字符串文本的测试调用会进行指针比较,这可能不是您想要的。
这是我更通用的解决方案。 仅当 N 个连续参数对于 N 个参数的所有块都相等时,compareConsecutive<N>
才会返回 true。
#include <iostream>
#include <tuple>
#include <utility>
template <std::size_t Start, typename IndexSequence> struct MakeIndexSequenceHelper;
template <std::size_t Start, std::size_t... Is>
struct MakeIndexSequenceHelper<Start, std::index_sequence<Is...>> {
using type = std::index_sequence<(Start + Is)...>;
};
template <std::size_t Start, std::size_t Length>
struct MakeIndexSequence : MakeIndexSequenceHelper<Start, std::make_index_sequence<Length>> {};
template <typename T, typename U>
bool allAreSame (const T&, const U&) {
return false;
}
template <typename T>
bool allAreSame (const T& t1, const T& t2) {
return t1 == t2;
}
template <typename T, typename U, typename... Args>
bool allAreSame (const T&, const U&, const Args&...) {
return false;
}
template <typename T, typename... Args>
bool allAreSame (const T& t1, const T& t2, const Args&... args) {
return allAreSame(t1, t2) && allAreSame(t1, args...);
}
template <typename Tuple, std::size_t... Is>
bool allAreSameHelper (Tuple&& tuple, std::index_sequence<Is...>) {
return allAreSame (std::get<Is>(std::forward<Tuple>(tuple))...);
}
template <std::size_t N, typename... Args>
bool allAreSameHelper (Args&&... args) {
return allAreSameHelper (std::forward_as_tuple(std::forward<Args>(args)...), std::make_index_sequence<N>{});
}
template <std::size_t N, typename... Args> bool compareConsecutive (Args&&...);
template <std::size_t N>
bool compareConsecutive() {return true;}
template <std::size_t N, typename Tuple, std::size_t... Is>
bool compareConsecutiveHelper (Tuple&& tuple, std::index_sequence<Is...>) {
return compareConsecutive<N> (std::get<Is>(std::forward<Tuple>(tuple))...);
}
template <std::size_t N, std::size_t Start, std::size_t Length, typename... Args>
bool compareConsecutiveHelper (Args&&... args) {
return compareConsecutiveHelper<N> (std::forward_as_tuple(std::forward<Args>(args)...), typename MakeIndexSequence<Start, Length>::type{});
}
template <std::size_t N, typename... Args>
bool compareConsecutive (Args&&... args) {
return allAreSameHelper<N>(std::forward<Args>(args)...) && compareConsecutiveHelper<N, N, sizeof...(Args) - N>(args...);
}
int main() {
std::cout << std::boolalpha << allAreSame("hi", "hi", "hi", "hi", "hi", "hi") << 'n'; // true
std::cout << compareConsecutive<2>(1, 1, "hi", "hi") << 'n'; // true
std::cout << compareConsecutive<2>(1, "hi", "hi", "hi") << 'n'; // false
std::cout << compareConsecutive<3>(1, 1, 1, "hi", "hi", "hi", 4.5, 4.5, 4.5) << 'n'; // true
std::cout << compareConsecutive<5>(1, 1, 1, 1, 1, "hi", "hi", "hi", "hi", "hi") << 'n'; // true
std::cout << compareConsecutive<5>(1, 1, 1, 1, 2, "hi", "hi", "hi", "hi", "hi") << 'n'; // false
}
相关文章:
- 在不传递参数数量且只有3个点的情况下,如何使用变差函数
- 如何使用可变参数模板强制转换每个变体类型
- 关于如何在具有单个参数的变体构造中选择替代方案?
- 调用参数排列不变函数 f(i++, i++)
- 参数归纳与标准::变体
- 模板化回调参数的逆变,如 C# 中的逆变
- 如何在没有参数包的情况下编写变差函数
- 通过具有嵌套类的工厂类获取多个变异类模板参数包
- 获取模板参数的成员变量值列表
- 保留短 lambda 用作函数的中间参数,使用 clang 格式保持不变
- 如何定义变体<x,y,z>提取模板参数的子类型
- 正确对齐内存模板,参数顺序不变
- 递归中不同参数类型的变元模板函数
- 通过函数指针传递给变差函数的参数会更改其值
- 提升预定义为带有参数的全局 lambda 的变体访问者
- 使用可变参数模板参数提升变体访问者
- boost ::变体 - 为什么模板参数比const字符串参数具有更高的优先级
- 将变参数包中的值加载到临时数组中
- 使用额外参数提升变体访客
- 正在将动态数组元素解析为参数?(变音符)