模板元程序查找相似的连续类型名

时间:2018-11-05 09:30:36

标签: c++ c++11 variadic-templates template-meta-programming typetraits

我是模板元编程的新手,并试图创建一个程序来查找参数包是否具有连续的相同类型名称。例如<int, int><int, char, char>将返回true,而<int,char><int, char, int>则不会。

我设法编写了这段代码,但似乎正在将参数包的每个值与其自身进行比较。我只是在寻找一种方法来迭代参数包的值,以与它的连续元素进行比较。

template<typename T, typename U>
struct sameTypename{
    enum {value = false};
};

template<typename T>
struct sameTypename<T, T>{
    enum {value = true};
};

template <typename T, typename ...args>
struct consTypename{
    enum {value = (sameTypename<consTypename<args...>, consTypename<args...>>::value)};
};

template <typename T>
struct consTypename<T, T>{
    enum {value = true};
};

template <typename T>
struct consTypename<T>{
    enum {value = false};
};

3 个答案:

答案 0 :(得分:8)

您在这里:

#include <type_traits>

template <typename ...P> struct has_adjacent_same_types : std::false_type {};
template <typename A, typename B, typename ...P> struct has_adjacent_same_types<A, B, P...>
    : std::bool_constant<std::is_same_v<A,B> || has_adjacent_same_types<B, P...>::value> {};

我用: std::false_type {};: std::bool_constant<X> {};代替了
分别为{enum{value = false};};{enum{value = X};};,但这只是偏好设置。


我使用的某些功能来自C ++ 17。如果您使用的是旧版本,请注意:

  

std::bool_constantstd::is_same_v仅从C ++ 17开始可用(但您可以在之前使用std::integral_constantstd::is_same<>::value)。

     

(c)@ max66

答案 1 :(得分:1)

HolyBlackCat解决方案的一种变体。

template <typename ...>
struct has_adjacent_same_types : public std::false_type
 { };

template <typename T0, typename ... Ts>
struct has_adjacent_same_types<T0, T0, Ts...> : public std::true_type
 { };

template <typename T0, typename T1, typename ... Ts>
struct has_adjacent_same_types<T0, T1, Ts...>
   : public has_adjacent_same_types<T1, Ts...>
 { };

两个更简单的专业化,而不仅仅是一个更复杂。

基本上是相同的(我想),但是我发现阅读和理解有点清楚。

答案 2 :(得分:1)

我还提出了一种完全不同的解决方案,该解决方案使用模板折叠(不幸的是,只有C ++ 17或更高版本)而不是模板递归。

1541415288860
Mon Nov 05 2018 
2018 
54 
48 
13
1:54:48 PM

如果要检查的类型列表中可能有template <typename...> struct sae_helper; template <typename ... Ts, typename ... Us> struct sae_helper<std::tuple<Ts...>, std::tuple<Us...>> : public std::bool_constant<(std::is_same_v<Ts, Us> || ...)> { }; template <typename ... Ts> struct some_adjacent_equal : public sae_helper<std::tuple<void, Ts...>, std::tuple<Ts..., void>> { }; 类型,则显然必须使用其他类型来代替voidsae_helper调用some_adjacent_equal。 / p>

我认为,在类型列表很长的情况下,此解决方案优于递归解决方案,因为避免编译器模板递归限制。

如果您可以使用C ++ 14,则可以按以下方式使用void函数代替模板折叠(并使用标记类型代替void)

constexpr

但是,通过这种方式,您会松开短路或评估。