简介
我正在寻找一种模式,用于将C++类型的特征转换为与其对应的变量。如果使用methodology来解决这个问题,那么使用generative programming patterns来自动完成任务将是理想的选择。
示例
请执行以下操作:
std::is_same<T, U>::value;
我想写一个像这样工作的特征:
std::are_same<T1, T2, T3, T4>::value;
当前方法
实现are_same
很简单;寻找一个通用的解决方案我们可以想出一个工具来实现通用量化的任何变量特征:
template<template<class,class> class F, typename...Ts>
struct Univ;
template<template<class, class> class F, typename T, typename U, typename...Ts>
struct Univ<F, T, U, Ts...>
{
static const int value = F<T, U>::value && Univ<F, U, Ts...>::value;
};
template<template<class, class> class F, typename T>
struct Univ<F, T>
{
static const int value = 1;
};
因此,例如are_same
可以是
Univ<is_same,int, int, int>::value
在创建are_classes
、are_scalars
等特征时,这一点也适用
泛化
细微的调整可能会给出存在量化,而不是之前的代码片段(用||
替换&&
),这样我们就可以用下面的方式创建像exist_same
这样的特征:
Exist<is_same, int, double, float>::value
问题
上一篇关于type traits的文章概括了
操作主要类型categories
如何对如下类型特征进行泛化:
enable_if -> enable_if_any // enable if any clause is true
enable_if_all // enalbe if all clauses are true
enable_for // enable only for the type provided
上面的exist_same
示例过于简单。对正确的实现有什么想法吗?
有一些type_traits可以“返回”修改过的类型。对于将这些扩展到任意数量类型的实现,有什么建议吗?
有没有让type_traits 不能扩展到任意数量的类型参数的?
发布于 2014-07-11 06:12:49
我不完全理解您到底想实现什么,但以下帮助程序可能会很有用,从bool_sequence
开始
#include <type_traits>
// Note: std::integer_sequence is C++14,
// but it's easy to use your own version (even stripped down)
// for the following purpose:
template< bool... Bs >
using bool_sequence = std::integer_sequence< bool, Bs... >;
// Alternatively, not using C++14:
template< bool... > struct bool_sequence {};
接下来,您可以检查所有或任何布尔值,或者使用以下内容进行设置:
template< bool... Bs >
using bool_and = std::is_same< bool_sequence< Bs... >,
bool_sequence< ( Bs || true )... > >;
template< bool... Bs >
using bool_or = std::integral_constant< bool, !bool_and< !Bs... >::value >;
它们可以作为更高级、更专业的特性的构建块而派上用场。例如,您可以这样使用它们:
typename< typename R, bool... Bs > // note: R first, no default :(
using enable_if_any = std::enable_if< bool_or< Bs... >::value, R >;
typename< typename R, bool... Bs > // note: R first, no default :(
using enable_if_all = std::enable_if< bool_and< Bs... >::value, R >;
typename< typename T, typename... Ts >
using are_same = bool_and< std::is_same< T, Ts >::value... >;
发布于 2016-07-08 23:47:47
您还可以使用std::conditional
来实现enable_if_all
和enable_if_any
#include <type_traits>
#include <iostream>
#include <initializer_list>
#include <string>
namespace detail
{
template <typename... Conds>
struct and_ : std::true_type {};
template <typename... Conds>
struct or_ : std::false_type {};
template <typename Cond, typename... Conds>
struct and_<Cond, Conds...>
: std::conditional<Cond::value, detail::and_<Conds...>, std::false_type>::type {};
template <typename Cond, typename... Conds>
struct or_<Cond, Conds...>
: std::conditional<Cond::value, std::true_type, detail::and_<Conds...>>::type {};
}
template <typename... T>
using are_all_pod = detail::and_<std::is_pod<T>...>;
template <typename... T>
using any_is_pod = detail::or_<std::is_pod<T>...>;
template <typename... Args, typename = typename std::enable_if<are_all_pod<Args...>::value>::type>
void f(Args... args)
{
(void)std::initializer_list<int>{(std::cout << args << '\n' , 0)...};
}
template <typename... Args, typename = typename std::enable_if<any_is_pod<Args...>::value>::type>
void g(Args... args)
{
(void)std::initializer_list<int>{(std::cout << args << '\n' , 0)...};
}
int main()
{
std::string s = "hello"; // non pod
//f(1, 1.2, s); // this will fail because not all types are pod
g(1, 1.2, s); // this compiles because there is at least one pod in argument pack
}
https://stackoverflow.com/questions/24687026
复制相似问题