我是模板元编程的新手,并试图创建一个程序来查找参数包是否具有连续的相同类型名称。例如<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};
};
答案 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_constant
和std::is_same_v
仅从C ++ 17开始可用(但您可以在之前使用std::integral_constant
和std::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>>
{ };
类型,则显然必须使用其他类型来代替void
从sae_helper
调用some_adjacent_equal
。 / p>
我认为,在类型列表很长的情况下,此解决方案优于递归解决方案,因为避免编译器模板递归限制。
如果您可以使用C ++ 14,则可以按以下方式使用void
函数代替模板折叠(并使用标记类型代替void)
constexpr
但是,通过这种方式,您会松开短路或评估。