有没有办法比较每种类型的可变参数模板的值?
template<typename... S>
class Signature {
// this is not valid syntax
S... values;
bool equals(S... s) {
// this is not either
bool eq = true;
eq &= s... &= values...;
return eq;
}
};
示例:
Signature<int, bool> s(5, true);
s.equals(5, true); // should result in 1
答案 0 :(得分:4)
此:
S... values;
是不正确的。你不能有这样的包装声明(不幸的是)。您必须将所有值放在某些内容中,例如:
std::tuple<S...> values;
一旦你这样做,比较它们很简单。只需使用==
:
template<typename... S>
struct Signature {
std::tuple<S...> values;
bool equals(Signature<S...> const& rhs) const {
return values == rhs.values;
}
bool equals(S const&... rhs) const {
// forward here to produce a tuple<S const&...> and avoid an unnecessary copy
return values == std::forward_as_tuple(rhs...);
}
};
答案 1 :(得分:2)
在c++17我们只需:
std::tuple<S...> values;
bool equals(S const&...s) const {
return std::apply([&](S const&... values){
return ((values==s)&&...);
}, values);
}
由于S... values;
不合法。
在c++14中,最好的方法是编写自己的apply
:
namespace details{
template<std::size_t...Is, class F, class Tuple>
decltype(auto) apply(std::index_sequence<Is...>, F&& f, Tuple&&t){
using std::get;
return std::forward<F>(f)( get<Is>( std::forward<Tuple>(t) )... );
}
}
template<class F, class Tuple>
decltype(auto) apply( F&& f, Tuple&& tuple )
using dT=std::decay_t<Tuple>;
auto size=std::tuple_size<dT>{};
return details::apply( std::make_index_sequence<size>{}, std::forward<F>(f), std::forward<Tuple>(tuple) );
}
并将其放入namespace notstd
。你还需要放置折叠:
return ((values==s)&&...);
与
bool r = true;
using discard=int[];
(void)discard{0,(void(
r = r && (values==s)
),0)...};
return r;
在c++11中,您需要将decltype(auto)
替换为尾随返回类型,并实现自己的索引序列代码。
答案 2 :(得分:1)
我能看到的真正问题是......什么是
std::tuple
你班上的?
据我所知,这不是C ++。
我想您可以将值保存在std::tuple<S...> value;
s
所以(如果你不想把你的std::tuple
放在#include <tuple>
#include <utility>
#include <iostream>
template <typename ... Ts>
struct Signature
{
std::tuple<Ts...> values;
Signature (Ts && ... ts) : values { std::forward<Ts>(ts) ... }
{ }
template <std::size_t ... Is>
bool equalsH (std::index_sequence<Is...> const &, Ts const & ... ts)
{ return ((ts == std::get<Is>(values)) && ... ); }
bool equals (Ts const & ... ts)
{ return equalsH(std::make_index_sequence<sizeof...(Ts)>{}, ts...); }
};
int main ()
{
Signature<int, bool> s { 5, true };
std::cout << s.equals(5, true) << std::endl; // print 1
std::cout << s.equals(5, false) << std::endl; // print 0
std::cout << s.equals(6, false) << std::endl; // print 0
std::cout << s.equals(6, true) << std::endl; // print 0
}
并比较元组,这很简单但不好笑)你的代码中的真正问题与使用有关元组。
基于新的折叠表达式
,我在C ++ 17中提出了以下解决方案equalH()
在C ++ 14中,你不能像在C ++ 17中那样使用fold表达式,所以你必须修改辅助函数( template <std::size_t ... Is>
bool equalsH (std::index_sequence<Is...> const &, Ts const & ... ts)
{
using unused = int[];
bool ret { true };
(void)unused { 0, (void(ret &= (ts == std::get<Is>(values))), 0) ... };
return ret;
}
);我建议如下
std::make_index_sequence
不幸的是std::index_sequence
和std::make_index_sequence
仅从C ++ 14开始可用,因此前面的示例在C ++ 11中不起作用;但是创建std::index_sequence
和bool equals (Ts && ... ts)
{ return values == std::forward_as_tuple( std::forward<Ts>(ts) ... ); }
的替代并不困难,如果你想要它,你可以使用元组比较解决方案
help(RLdata500)