- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在项目中开发了某种元对象机制,以便将任何类型的类型名称和属性关联到对象(参见结果 here )。我有一个肮脏的代码在工作,我正试图让它更干净。给定以下虚拟结构:
struct A
{
using Self = A;
using Base = void;
static std::string get_type_name(){ return { "A" }; }
static std::vector<int> get_properties(){ return { 0 }; }
};
#define SELF(class_name)\
using Base = Self;\
using Self = class_name;
struct AA : A
{
SELF(AA)
static std::string get_type_name() { return { "AA" }; }
};
struct AAA : AA
{
SELF(AAA)
static std::string get_type_name(){ return { "AAA" }; }
static std::vector<int> get_properties(){ return { 2, 1 }; }
};
我最终使用这段代码来获取对象在其层次结构中的类型名称:
// when the type has no Base member:
template<
typename T,
typename std::enable_if<std::is_same<typename T::Base, void>::value>::type* = nullptr
>
typename std::vector<decltype(T::Self::get_type_name())> get_type_names()
{
return { T::Self::get_type_name() };
}
// when the type has a Base member:
template<
typename T,
typename std::enable_if<!std::is_same<typename T::Base, void>::value>::type* = nullptr
>
typename std::vector<decltype(T::Self::get_type_name())> get_type_names()
{
auto data = get_type_names<typename T::Base>();
data.insert(data.begin(), T::Self::get_type_name());
return data;
}
还有类似的属性:
template<
typename T,
typename std::enable_if<std::is_same<typename T::Base, void>::value>::type* = nullptr
>
decltype(T::Self::get_properties()) get_properties()
{
return { T::Self::get_properties() };
}
template<
typename T,
typename std::enable_if<!std::is_same<typename T::Base, void>::value>::type* = nullptr
>
decltype(T::Self::get_properties()) get_properties()
{
auto data = get_properties<typename T::Base>();
auto self_data = T::Self::get_properties();
data.insert(data.begin(), self_data.begin(), self_data.end());
return data;
}
使用此代码段测试代码时:
template<typename T>
void print()
{
std::cout << T::get_type_name() << std::endl << "\thas types:" << std::endl;
for(auto type_name : get_type_names<T>())
{
std::cout << "\t\t" << type_name << std::endl;
}
std::cout << "\thas properties:" << std::endl;
for(auto property : get_properties<T>())
{
std::cout << "\t\t" << property << std::endl;
}
}
int main()
{
print<A>();
print<AA>();
print<AAA>();
return 0;
}
我得到以下输出:
A
has types:
A
has properties:
0
AA
has types:
AA
A
has properties:
0
0
AAA
has types:
AAA
AA
A
has properties:
2
1
0
0
第一个原型(prototype)适用于名称,但是一旦声明了一个没有属性的对象,其基类中的属性就会被复制。有人看到了解决问题的简单方法吗?
奖励问题:元函数的实现非常相似,有人提示我如何分解代码吗?
完整的实例可用here
最佳答案
这是一个不完整的解决方案,可以让您走上正轨。首先,一切都取决于遍历基地名单。因此,让我们将其考虑到它自己的元函数中:
template <class... > struct typelist { };
template <class T, class... Bases>
struct get_bases
: get_bases<typename T::Base, Bases..., T>
{ };
template <class... Bases>
struct get_bases<void, Bases...>
{
using type = typelist<Bases...>;
};
template <class T>
using get_bases_t = typename get_bases<T>::type;
现在,get_bases_t<A>
是typelist<A>
和 get_bases_t<AAA>
是typelist<AAA, AA, A>
.现在,您所有的其他功能都只是基于沿着该类型列表走下去并对其进行操作。所以让我们添加一个简单的方法来做到这一点:
template <class T> struct tag { using type = T; };
template <class... Ts>
auto for_each(typelist<Ts...>) {
return [](auto&& f){
using swallow = int[];
(void)swallow{0,
(void(f(tag<Ts>{})), 0)...
};
};
}
现在,获取所有属性就是将所有碱基转换为对应的 get_properties()
的问题函数,然后调用所有唯一的函数。您可能可以在编译时挑选出独特的功能,但这也适用:
template <class T>
std::vector<int> get_properties() {
using bases = get_bases_t<T>;
using F = std::vector<int>(*)();
F last = nullptr;
std::vector<int> props;
for_each(bases{})([&](auto t){
using B = typename decltype(t)::type;
F cur = B::get_properties;
if (cur != last) {
auto next = cur();
props.insert(props.end(), next.begin(), next.end());
last = cur;
}
});
return props;
}
这种方法对于获取类型名称也非常简单:
template <class T>
std::vector<std::string> get_type_names()
{
using bases = get_bases_t<T>;
std::vector<std::string> names;
names.reserve(len_v<bases>); // TODO
for_each(bases{})([&](auto t){
names.push_back(decltype(t)::get_type_name());
});
return names;
}
或者,在这种情况下,只需:
template <class... Bs>
std::vector<std::string> get_type_names_impl(typelist<Bs...>) {
return {Bs::get_type_name()...};
}
template <class T>
std::vector<std::string> get_type_names()
{
return get_type_names_impl(get_bases_t<T>);
}
关于c++ - 使用 "static virtual"函数的元对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39274948/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!