Je voudrais écrire une fonction qui pourrait être appelé comme:
template<typename T, int N>
void func(const Elem<T, N> & ... /*N elements*/,
Elem<T, N> & ... /* N elements*/)
En ce que je sais, ce que vous demandez est pas facile d'exprimer la langue disponible.
Le mieux que je peux imaginer, est d'écrire la fonction func()
comme suit
template <typename ... Es>
typename std::enable_if<checkElems<Es...>::value>::type
func (Es & ... es)
{
using type = typename checkElems<Es ...>::type; // former T
constexpr std::size_t num { sizeof...(Es) >> 1 }; // former N
// ...
}
Où func()
reçoit une liste (Es & ... es
) des arguments et la fonction est SFINAE activée uniquement si la liste relative des types (Es ...
) satisfaire une liste d'exigences implémentées dans les caractères de type personnalisés checkElems
(voir l'exemple suivant).
Ainsi, le chèque checkElems
suivant que:
- il y a au moins un type d'argument
- le premier argument est sous la forme
Elem<T, N> const
- le nombre de type d'argument est exactement
2 * N
- la premiers
N
types sont égaux les uns aux autres
- les types suivants
N
sont égaux les uns aux autres
- ajoutant
const
les N
types suivants, ils sont égaux à la première N
- sans ajouter
const
, les N
types suivants sont différents pour la première N
Inside func()
vous êtes en mesure de utilisez type
(voir l'exemple), c'est le type T
dans Elem<T, N>
, et num
, c'est la valeur N
dans Elem<T, N>
.
Vous pouvez faire ces contrôles mais je ne sais pas si c'est une bonne idée.
Un exemple compilable
#include <tuple>
#include <type_traits>
template<typename T, std::size_t N>
struct Elem {};
template <typename>
struct extrElem;
template <typename T, std::size_t N>
struct extrElem<Elem<T, N> const>
{
using type = T;
static constexpr std::size_t num { N };
};
template <std::size_t, std::size_t, typename ...>
struct extrTypes;
template <std::size_t Skip, std::size_t Num, typename ... Es, typename T0,
typename ... Ts>
struct extrTypes<Skip, Num, std::tuple<Es...>, T0, Ts...>
{ using type = typename extrTypes<
Skip-1U, Num, std::tuple<Es...>, Ts...>::type; };
template <std::size_t Num, typename ... Es, typename T0, typename ... Ts>
struct extrTypes<0U, Num, std::tuple<Es...>, T0, Ts...>
{ using type = typename extrTypes<
0U, Num-1U, std::tuple<Es..., T0>, Ts...>::type; };
template <typename ... Es, typename T0, typename ... Ts>
struct extrTypes<0U, 0U, std::tuple<Es...>, T0, Ts...>
{ using type = std::tuple<Es...>; };
template <typename ... Es>
struct extrTypes<0U, 0U, std::tuple<Es...>>
{ using type = std::tuple<Es...>; };
template <typename>
struct sameContTypes : public std::false_type
{ };
template <template <typename ...> class C, typename T0, typename ... Ts>
struct sameContTypes<C<T0, Ts...>>
: public std::is_same<C<T0, Ts...>, C<Ts..., T0>>
{ };
template <typename E0, typename ... Es>
struct checkElems
{
static constexpr std::size_t num { extrElem<E0>::num };
using type = typename extrElem<E0>::type;
using lt1 = typename extrTypes<0U, num, std::tuple<>, E0, Es...>::type;
using lt2 = typename extrTypes<num, num, std::tuple<>, E0, Es...>::type;
static constexpr bool value {
((num << 1) == 1U + sizeof...(Es))
&& sameContTypes<lt1>::value
&& sameContTypes<lt2>::value
&& (true == std::is_same<E0,
typename std::tuple_element<0U, lt2>::type const>::value)
&& (false == std::is_same<E0,
typename std::tuple_element<0U, lt2>::type>::value) };
};
template <typename ... Es>
typename std::enable_if<checkElems<Es...>::value>::type
func (Es & ... es)
{
using type = typename checkElems<Es ...>::type; // former T
constexpr std::size_t num { sizeof...(Es) >> 1 }; // former N
// ...
}
int main()
{
Elem<int, 3> ei3;
Elem<int, 4> ei4;
Elem<int, 3> const eci3;
Elem<int, 4> const eci4;
func(eci3, eci3, eci3, ei3, ei3, ei3); // compile
//func(eci3, eci3, eci3, ei3, eci3, ei3); // compilation error
//func(eci3, eci3, eci3, ei3, ei3, ei4); // compilation error
//func(eci3, eci3, eci4, ei3, ei3, ei3); // compilation error
//func(eci4, eci4, eci4, ei4, ei4, ei4); // compilation error
//func(eci4, eci4, eci4, eci4, ei4, ei4, ei4); // compilation error
func(eci4, eci4, eci4, eci4, ei4, ei4, ei4, ei4); // compile
}
Arrêtez la crainte des frais généraux et commencer à mesurer. – nwp
quels temporaires craignez-vous? Je ne vois que des références en tant que paramètres – user463035818
C++ 11, C++ 14 ou C++ 17? – max66