- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在编写一些程序,通过代码生成自动调用一些 API。
在某些情况下,我需要将 Source
类型转换为 Target
类型,但这些类型都装饰有指针、const 等。所以我需要做的是删除所有装饰,如指针、常量、数组等,获取普通类型以将其映射到另一个类型,稍后,将装饰应用回新类型。
该实现有很多模板特化。代码后的问题。我不能使用 constexpr
元编程,因为我需要让它与 VS2013 一起工作。
template <class T>
struct TypeIs {
using type = T;
};
template <class T>
struct GetPlainType : TypeIs<typename std::decay<T>::type> {};
template <class T>
struct GetPlainType<T&> : TypeIs<typename GetPlainType<T>::type> {};
template <class T>
struct GetPlainType<T const &> : TypeIs<typename GetPlainType<T>::type> {};
template <class T>
struct GetPlainType<T &&> : TypeIs<typename GetPlainType<T>::type> {};
template <class T>
struct GetPlainType<T const &&> : TypeIs<typename GetPlainType<T>::type> {};
template <class T>
struct GetPlainType<T*> : TypeIs<typename GetPlainType<T>::type> {};
template <class T>
struct GetPlainType<T const *> : TypeIs<typename GetPlainType<T>::type> {};
template <class T>
struct GetPlainType<T const> : TypeIs<typename GetPlainType<T>::type> {};
template <class T>
struct GetPlainType<T[]> : TypeIs<typename GetPlainType<T>::type> {};
template <class T>
struct GetPlainType<T const[]> : TypeIs<typename GetPlainType<T>::type> {};
template <class T, std::size_t I>
struct GetPlainType<T[I]> : TypeIs<typename GetPlainType<T>::type> {};
template <class T, std::size_t I>
struct GetPlainType<T const [I]> : TypeIs<typename GetPlainType<T>::type> {};
template <class T>
using GetPlainType_t = typename GetPlainType<T>::type;
template <class Decorated, class Plain>
struct CopyDecorations : TypeIs<Plain> {};
template <class T, class Plain>
struct CopyDecorations<T const, Plain> :
TypeIs<typename CopyDecorations<T, Plain const>::type> {};
template <class T, class Plain>
struct CopyDecorations<T *, Plain> :
TypeIs<typename CopyDecorations<T, Plain *>::type> {};
template <class T, class Plain>
struct CopyDecorations<T const *, Plain> :
TypeIs<typename CopyDecorations<T, Plain const *>::type> {};
template <class T, class Plain>
struct CopyDecorations<T &, Plain> :
TypeIs<typename CopyDecorations<T, Plain &>::type> {};
template <class T, class Plain>
struct CopyDecorations<T const &, Plain> :
TypeIs<typename CopyDecorations<T, Plain const &>::type> {};
template <class T, class Plain>
struct CopyDecorations<T &&, Plain> :
TypeIs<typename CopyDecorations<T, Plain &&>::type> {};
template <class T, class Plain>
struct CopyDecorations<T const &&, Plain> :
TypeIs<typename CopyDecorations<T, Plain const &&>::type> {};
template <class T, class Plain>
struct CopyDecorations<T[], Plain> :
TypeIs<typename CopyDecorations<T, Plain[]>::type> {};
template <class T, class Plain>
struct CopyDecorations<T const [], Plain> :
TypeIs<typename CopyDecorations<T, Plain const []>::type> {};
template <class T, class Plain, std::size_t I>
struct CopyDecorations<T [I], Plain> :
TypeIs<typename CopyDecorations<T, Plain[I]>::type> {};
template <class T, class Plain, std::size_t I>
struct CopyDecorations<T const [I], Plain> :
TypeIs<typename CopyDecorations<T, Plain const [I]>::type> {};
template <class Decorated, class Plain>
using CopyDecorations_t = typename CopyDecorations<Decorated, Plain>::type;
int main()
{
static_assert(std::is_same<GetPlainType_t<int>, int>{}, "");
static_assert(std::is_same<GetPlainType_t<int const>, int>{}, "");
static_assert(std::is_same<GetPlainType_t<int *>, int>{}, "");
static_assert(std::is_same<GetPlainType_t<int **>, int>{}, "");
static_assert(std::is_same<GetPlainType_t<int * &>, int>{}, "");
static_assert(std::is_same<GetPlainType_t<int ** &>, int>{}, "");
static_assert(std::is_same<GetPlainType_t<int const * []>, int>{}, "");
static_assert(std::is_same<GetPlainType_t<int const **[][3][5]>, int>{}, "");
static_assert(std::is_same<CopyDecorations_t<int, double>, double>{}, "");
static_assert(std::is_same<CopyDecorations_t<int const, double>, double const>{}, "");
static_assert(std::is_same<CopyDecorations_t<int *, double>, double *>{}, "");
static_assert(std::is_same<CopyDecorations_t<int **, double>, double **>{}, "");
static_assert(std::is_same<CopyDecorations_t<int[], double>, double[]>{}, "");
static_assert(std::is_same<CopyDecorations_t<int[3], double>, double[3]>{}, "");
//******************THE TESTS BELOW DO NOT WORK
//static_assert(std::is_same<CopyDecorations_t<int[][3], double>, double[][3]>{}, "");
//static_assert(std::is_same<CopyDecorations_t<int * &, double>, double * &>{}, "");
// static_assert
// (
//std::is_same<CopyDecorations_t<int const * [], double>,
// double const * []>{}, "");
// static_assert
// (std::is_same<CopyDecorations_t<int const **[][3][5], double>,
// double const **[][3][5]>{}, "");
}
问题:
main
函数),我该如何修复它们?最佳答案
我发现这个问题确实是关于 SO 上的 C++ 元编程最有趣的问题之一。
我喜欢尝试找到合适的解决方案。谢谢你。 :-)
它遵循一个最小的工作示例。
它并不完整,但它提供了一种可能的方法来实现这一点。f
函数(好吧,你可以在你的代码中选择一个更好的名字)接受两个模板参数:要清理的类型和要装饰.
它返回一个模板类型 (types
),它引入了两个 using 声明,basic
和 decorated
,第一个模板参数清理为 basic
和第二个装饰为decorated
。
它一次完成所有工作(清理和装饰)。您仍然可以只使用第一个参数,在这种情况下 decorated
默认为装饰的 char
类型。
完整代码如下:
#include<type_traits>
#include<cstddef>
static constexpr std::size_t N = 42;
template<std::size_t N>
struct choice: choice<N-1> {};
template<>
struct choice<0> {};
template<typename T, typename U>
struct types {
using basic = T;
using decorated = U;
};
template<typename T, typename U>
constexpr auto
f(choice<0>) { return types<T, U>{}; }
template<typename T, typename U,
typename = std::enable_if_t<std::is_pointer<T>::value>>
constexpr auto f(choice<1>) {
auto t = f<std::remove_pointer_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::add_pointer_t<D>>{};
}
template<typename T, typename U,
typename = std::enable_if_t<std::is_lvalue_reference<T>::value>>
constexpr auto f(choice<2>) {
auto t = f<std::remove_reference_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::add_lvalue_reference_t<D>>{};
}
template<typename T, typename U,
typename = std::enable_if_t<std::is_rvalue_reference<T>::value>>
constexpr auto f(choice<3>) {
auto t = f<std::remove_reference_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::add_rvalue_reference_t<D>>{};
}
template<typename T, typename U,
typename = std::enable_if_t<std::is_array<T>::value>>
constexpr auto f(choice<4>) {
auto t = f<std::remove_extent_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::conditional_t<(0==std::extent<T>::value), D[], D[std::extent<T>::value]>>{};
}
template<typename T, typename U,
typename = std::enable_if_t<std::is_const<T>::value>>
constexpr auto f(choice<5>) {
auto t = f<std::remove_const_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::add_const_t<D>>{};
}
template<typename T, typename U,
typename = std::enable_if_t<std::is_volatile<T>::value>>
constexpr auto f(choice<6>) {
auto t = f<std::remove_volatile_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::add_volatile_t<D>>{};
}
template<typename T, typename U = char>
constexpr auto f() {
return f<T, U>(choice<N>{});
}
int main() {
// something complex to show that it seems to work
static_assert(std::is_same<
decltype(f<const int ** const &&, char>()),
types<int, const char ** const &&>
>::value, "!");
// some of the OP's examples (the most interesting)
static_assert(std::is_same<decltype(f<int, int>()), types<int, int>>::value, "!");
static_assert(std::is_same<decltype(f<int const, int>()), types<int, int const>>::value, "!");
static_assert(std::is_same<decltype(f<int *, int>()), types<int, int *>>::value, "!");
static_assert(std::is_same<decltype(f<int **, double>()), types<int, double **>>::value, "!");
static_assert(std::is_same<decltype(f<int *&, int>()), types<int, int *&>>::value, "!");
static_assert(std::is_same<decltype(f<int **&, float>()), types<int, float **&>>::value, "!");
static_assert(std::is_same<decltype(f<int [3], char>()), types<int, char [3]>>::value, "!");
static_assert(std::is_same<decltype(f<int [], int>()), types<int, int []>>::value, "!");
static_assert(std::is_same<decltype(f<int [][3], double>()), types<int, double [][3]>>::value, "!");
static_assert(std::is_same<decltype(f<int const **[][3][5], int>()), types<int, int const **[][3][5]>>::value, "!");
// of course, you don't need to provide the second type if you don't need it
// in this case, types::decorated is defaulted to a decorated char type
f<int const **[][3][5]>();
}
除了因为 static_assert
而没有 constexpr
就无法编译的事实之外,您可以自由地删除它们并在运行时使用该函数。
实际上,它可能会变成一个无定义的解决方案,为声明提供正确的返回类型并使用一堆decltype
,但我怀疑它远非可读性。
编辑
正如 OP 所提到的,他不想(或者至少,他不能使用)constexpr
s。
它遵循了一个略有不同的解决方案,仍然基于之前的解决方案。
基本思想是将 f
用作带有 decltype
的未计算操作数。
这是完整的代码:
#include<type_traits>
#include<cstddef>
static const std::size_t N = 42;
template<std::size_t N>
struct choice: choice<N-1> {};
template<>
struct choice<0> {};
template<typename T, typename U>
struct types {
using basic = T;
using decorated = U;
};
template<typename T, typename U>
auto f(choice<0>) { return types<T, U>{}; }
template<typename T, typename U,
typename = std::enable_if_t<std::is_pointer<T>::value>>
auto f(choice<1>) {
auto t = f<std::remove_pointer_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::add_pointer_t<D>>{};
}
template<typename T, typename U,
typename = std::enable_if_t<std::is_lvalue_reference<T>::value>>
auto f(choice<2>) {
auto t = f<std::remove_reference_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::add_lvalue_reference_t<D>>{};
}
template<typename T, typename U,
typename = std::enable_if_t<std::is_rvalue_reference<T>::value>>
auto f(choice<3>) {
auto t = f<std::remove_reference_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::add_rvalue_reference_t<D>>{};
}
template<typename T, typename U,
typename = std::enable_if_t<std::is_array<T>::value>>
auto f(choice<4>) {
auto t = f<std::remove_extent_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::conditional_t<(0==std::extent<T>::value), D[], D[std::extent<T>::value]>>{};
}
template<typename T, typename U,
typename = std::enable_if_t<std::is_const<T>::value>>
auto f(choice<5>) {
auto t = f<std::remove_const_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::add_const_t<D>>{};
}
template<typename T, typename U,
typename = std::enable_if_t<std::is_volatile<T>::value>>
auto f(choice<6>) {
auto t = f<std::remove_volatile_t<T>, U>(choice<N>{});
using B = typename decltype(t)::basic;
using D = typename decltype(t)::decorated;
return types<B, std::add_volatile_t<D>>{};
}
template<typename T, typename U>
auto f() {
return f<T, U>(choice<N>{});
}
template<typename T, typename U = char>
using my_type = decltype(f<T, U>());
template<typename T, typename U = char>
using my_type_basic_t = typename decltype(f<T, U>())::basic;
template<typename T, typename U = char>
using my_type_decorated_t = typename decltype(f<T, U>())::decorated;
int main() {
int i = 42;
my_type_decorated_t<char *, int> ptr = &i;
// of course, it can still be used in a constant expression if needed
// constexpr my_type_decorated_t<char *, int> ptr = nullptr;
}
关于c++ - 元编程技巧 : how to simplify implementation of two metafunctions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39143903/
我经常在 C 标准文档中看到“实现定义”的说法,并且非常将其作为答案。 然后我在 C99 标准中搜索它,并且: ISO/IEC 9899/1999 (C99) 中第 §3.12 条规定: 3.12 I
“依赖于实现”中的“实现”是什么意思? “依赖于实现”和“依赖于机器”之间有什么区别? 我使用C,所以你可以用C解释它。 最佳答案 当 C 标准讨论实现时,它指的是 C 语言的实现。因此,C 的实现就
我刚刚在 Android-studio 中导入了我的项目,并试图在其中创建一个新的 Activity。但我无法在 android-studio 中创建 Activity 。我指的是here我看不到将目
我想知道您对为什么会发生此错误的意见。在陆上生产环境中,我们使用 CDH4。在我们的本地测试环境中,我们只使用 Apache Hadoop v2.2.0。当我运行在 CDH4 上编译的同一个 jar
我正在尝试集成第三方 SDK (DeepAR)。但是当我构建它时,它会显示一个错误。我试图修复它。如果我创建一个简单的新项目,它就可以正常工作。但是我现有的应用程序我使用相机和 ndk。请帮我找出错误
我很好奇为什么我们有 @Overrides 注释,但接口(interface)没有类似的习惯用法(例如 @Implements 或 @Implementation)。这似乎是一个有用的功能,因为您可能
我对 DAODatabase(适用于 Oracle 11 xe)的 CRUD 方法的实现感到困惑。问题是,在通常存储到 Map 集合的情况下,“U”方法(更新)会插入新元素或更新它(像 ID:Abst
Java-API 告诉我特定类实现了哪些接口(interface)。但有两种不同类型的信息,我不太确定这意味着什么。例如,对于“TreeSet”类:https://docs.oracle.com/en
我有一个接口(interface) MLService,它具有与机器学习算法的训练和交叉验证相关的基本方法,我必须添加两个接口(interface)分类和预测,它们将实现 MLService 并包含根
我一直想知道如何最好地为所有实现相同接口(interface)的类系列实现 equals()(并且客户端应该只使用所述接口(interface)并且永远不知道实现类)。 我还没有编写自己的具体示例,但
我有一个接口(interface)及其 2 个或更多实现, public interface IProcessor { default void method1() { //logic
我有同一个应用程序的免费版和高级版(几乎相同的代码,相同的类,到处都是“if”, list 中的不同包, list 中的进程名称相同)。主要 Activity 使用 IMPLICIT Intent 调
这是我为我的应用程序中的错误部分编写的代码 - (id)initWithData:(NSData *)data <-------- options:(NSUInteger)opti
请查找随附的代码片段。我正在使用此代码将文件从 hdfs 下载到我的本地文件系统 - Configuration conf = new Configuration(); FileSys
我想在 MongoDB 中使用 Grails2.5 中的“ElasticSearch”插件。我的“BuildConfig.groovy”文件是: grails.servlet.version = "3
我收到一条错误消息: fatal error: init(coder:) has not been implemented 对于我的自定义 UITableViewCell。该单元格未注册,在 Stor
得到这个错误 kotlin.NotImplementedError: An operation is not implemented: not implemented 我正在实现一个 ImageBut
typedef int Element; typedef struct { Element *stack; int max_size; int top; } Stack; //
Playground 代码 here 例子: interface IFoo { bar: number; foo?: () => void; } abstract class Abst
我想知道如何抑制警告: Category is implementing a method which will also be implemented by its primary class. 我
我是一名优秀的程序员,十分优秀!