我需要检查传递给函数的任何参数是否出现两次以上。基本上,我想要以下行为
no_unique<0,1,0,1,0,1>::value // returns 2
我知道finding the number of uniques上有一个问题,但它没有回答我的问题,因为该问题的解决方案返回了例如
C++11
但它没有说参数是出现一次,两次还是三次。
如何在>>> grid = []
>>> def solve(grid)
... global grid
...
中实现这一目标?
答案 0 :(得分:3)
效率不高但您可以使用以下内容:
#include <algorithm>
#include <type_traits>
template <size_t S, size_t... Sizes>
struct count;
template <size_t S>
struct count<S>: std::integral_constant<size_t, 0> {};
template <size_t S1, size_t... Sizes>
struct count<S1, S1, Sizes...>:
std::integral_constant<size_t, 1 + count<S1, Sizes...>{}> {};
template <size_t S1, size_t S2, size_t... Sizes>
struct count<S1, S2, Sizes...>:
count<S1, Sizes...> {};
template <size_t...>
struct max_count;
template <>
struct max_count<>: std::integral_constant<size_t, 0> { };
template <size_t S, size_t... Sizes>
struct max_count<S, Sizes...>:
std::integral_constant<size_t, std::max(1 + count<S, Sizes...>{},
max_count<Sizes...>::value)> { };
template <size_t... Sizes>
struct no_more_than_two: std::integral_constant<bool, max_count<Sizes...>{} <= 2> { };
static_assert(no_more_than_two<0,1,0,1>{}, "");
static_assert(!no_more_than_two<2,0,1,2,2>{}, "");
static_assert(!no_more_than_two<5,5,5>{}, "");
首先检索任何值的最大出现次数,然后将其与2进行比较。
如果您只有C ++ 11(不是C ++ 14),请将std::max
替换为自定义ct_max
:
template <typename T>
constexpr const T& ct_max(T const& t1, T const& t2) {
return t1 < t2 ? t2 : t1;
}
答案 1 :(得分:2)
滥用多重继承的答案:
#include <utility>
#include <type_traits>
template <std::size_t I>
struct wrap {};
template <std::size_t ... Is>
struct derived : wrap<Is>...
{
};
template <>
struct derived<> {
};
template <typename, typename, std::size_t...>
struct appearance_impl;
template <std::size_t... I2, std::size_t... I1, std::size_t I, std::size_t...Is>
struct appearance_impl<derived<I2...>, derived<I1...>, I, Is...>
: std::conditional<
std::is_base_of<wrap<I>, derived<I2...>>::value, // If I in I2 => false
std::false_type,
typename std::conditional<
std::is_base_of<wrap<I>, derived<I1...>>::value, // else if I in I1, add I to I2
appearance_impl<derived<I, I2...>, derived<I1...>, Is...>,
appearance_impl<derived<I2...>, derived<I, I1...>, Is...>
>::type
>::type
{
};
template <typename D2, typename D1>
struct appearance_impl<D2, D1> : std::true_type {};
template <std::size_t ...Is>
struct appearance : appearance_impl<derived<>, derived<>, Is...>::type { };
int main() {
static_assert(appearance<0,1,0,1>::value, "");
static_assert(!appearance<2,0,1,2,2>::value, "");
static_assert(!appearance<5,5,5>::value, "");
}
答案 2 :(得分:1)
这是一个更长的时间,但它应该非常有效,并且它避免了很多聪明。
// Map integers to types.
template< int i >
using intc = std::integral_constant< int, i >;
// Increment a type-integer.
template< typename intc >
using inc_intc = std::integral_constant< int, intc::value + 1 >;
// Count the appearances of an integer in a sequence.
template< int ... >
struct appearances { // Base case of induction: return zero for every value.
template< int i >
static intc< 0 > count( intc< i > );
};
// Recursive case: Add one to the base class count.
template< int i, int ... rem >
struct appearances< i, rem ... >
: appearances< rem ... > {
typedef appearances< rem ... > base;
using base::count;
static inc_intc< decltype( base::count( intc< i >{} ) ) >
count( intc< i > );
};
// Find the sequences in question with early exit.
template< typename acc, typename seq, typename = void >
struct no_triple_occurrence_impl // Base case: empty sequence, no triples.
: std::true_type {};
// Early exit case: found two instances of the next i.
template< typename acc, int i, int ... rem >
struct no_triple_occurrence_impl<
acc,
std::integer_sequence< int, i, rem ... >,
std::enable_if_t< decltype(
acc::count( intc< i >{} )
){} >= 2 >
> : std::false_type {};
// Recursive case: add the next i to the counter.
template< int ... done, int i, int ... rem >
struct no_triple_occurrence_impl<
appearances< done ... >,
std::integer_sequence< int, i, rem ... >,
std::enable_if_t< decltype(
appearances< done ... >::count( intc< i >{} )
){} < 2 >
> : no_triple_occurrence_impl<
appearances< i, done ... >, // Keep done... at the end for memoization.
std::integer_sequence< int, rem ... >
>::type {};
template< int ... seq >
constexpr bool no_triple_occurrence
= no_triple_occurrence_impl<
appearances<>,
std::integer_sequence< int, seq ... >
>::value;
(on Coliru。)
答案 3 :(得分:1)
我也可以玩吗?
以下是我的解决方案,主要基于部分模板专业化。
#include <iostream>
using IType = int; // or long? or unsigned? or size_t?
template <typename IT, IT ...>
struct intSeq
{ };
template <typename, typename, std::size_t>
struct no_more_than_val;
template <typename IT, IT I0, std::size_t M, IT Val, IT ... Is>
struct no_more_than_val<intSeq<IT, I0, Is...>, intSeq<IT, Val>, M>
{ static constexpr bool value
{ no_more_than_val<intSeq<IT, Is...>, intSeq<IT, Val>, M>::value }; };
template <typename IT, IT Val, std::size_t M, IT ... Is>
struct no_more_than_val<intSeq<IT, Val, Is...>, intSeq<IT, Val>, M>
{ static constexpr bool value
{ no_more_than_val<intSeq<IT, Is...>, intSeq<IT, Val>, M-1U>::value }; };
template <typename IT, IT I0, IT ... Is>
struct no_more_than_val<intSeq<IT, I0, Is...>, intSeq<IT, I0>, 0U>
{ static constexpr bool value { false }; };
template <typename IT, std::size_t M, IT Val>
struct no_more_than_val<intSeq<IT>, intSeq<IT, Val>, M>
{ static constexpr bool value { true }; };
template <typename, std::size_t>
struct no_more_than_list;
template <typename IT, std::size_t M>
struct no_more_than_list<intSeq<IT>, M>
{ static constexpr bool value { true }; };
template <typename IT, IT I0, IT ... Is>
struct no_more_than_list<intSeq<IT, I0, Is...>, 0U>
{ static constexpr bool value { false }; };
template <typename IT, std::size_t M, IT I0, IT ... Is>
struct no_more_than_list<intSeq<IT, I0, Is...>, M>
{
static constexpr bool value
{ no_more_than_val<intSeq<IT, Is...>, intSeq<IT, I0>, M-1U>::value
&& no_more_than_list<intSeq<IT, Is...>, M>::value };
};
template <IType ... Is>
struct appearance
: public no_more_than_list<intSeq<IType, Is...>, 2U>
{ };
int main()
{
std::cout << appearance<0,1,0,1>::value << std::endl; // print 1
std::cout << appearance<2,0,1,2,2>::value << std::endl; // print 0
std::cout << appearance<5,5,5>::value << std::endl; // print 0
}
如果您可以使用C ++ 14,则可以使用std::integer_sequence
代替intSeq
。无论如何,您可以使用std::integral_constant<IT, Val>
代替intSeq<IT, Val>
。
答案 4 :(得分:0)
使用boost.hana的简短且易读的版本:
#include <boost/hana/all_of.hpp>
#include <boost/hana/group.hpp>
#include <boost/hana/length.hpp>
#include <boost/hana/less.hpp>
#include <boost/hana/sort.hpp>
#include <boost/hana/tuple.hpp>
#include <boost/hana/type.hpp>
namespace hana = boost::hana;
template <int... ints>
struct appearance {
static constexpr bool value =
hana::all_of(
hana::transform(
hana::group(
hana::sort(
hana::make_tuple(hana::size_c<ints>...))),
hana::length),
hana::less.than(hana::size_c<3>));
};