- 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/
我是 F# 的菜鸟,目前正在阅读 F# 3.0 中的专家。 它是我学习的第一种编译语言(我只知道用 R 编程) 在第 6 章第 117 页,我们没有太多仪式性地介绍 静态让和静态成员。我真的不明白它是
我很迷茫。我已经花几个小时广泛地复习了我的两个类(class)。没有什么是静态的,没有什么是静态引用的,但我无法摆脱这个错误。 A 类文件 (ClassA.php) privateVariable =
关于类公共(public)类声明,请看这两段代码: public class Helper { public static void CallMeganFox(string phoneNumb
我如何使用“super”关键字从父类(super class)(类“aa”)引用“a1” class aa { protected static int a1 = 2; } public class
class Perkusja { boolean talerze = true; boolean beben = true; void zagrajNaBebnie() { Sys
我试图在编译 C++ 程序时静态链接库。 g++ (GCC) 4.8.5 20150623(红帽 4.8.5-4) $ g++ -std=c++11 -I/home/jerry/Desktop/tin
$ javac TestFilter.java TestFilter.java:19: non-static variable this cannot be referenced from a sta
这个问题在这里已经有了答案: How do I create a global, mutable singleton? (7 个答案) How can you make a safe static
“覆盖”静态数组时我遇到了一个棘手的问题。我有静态数组(为简单起见),它们在不同的派生类中具有固定长度,但在编译时仍然知道所有大小。我在基类中也有一个虚函数,但我不知道如何解决在派生类中覆盖这些数组和
我刚刚在遗留代码中发现了这一点。我知道使用宏,每当使用名称时,它都会被宏的内容替换。它们最常用于为数字常量提供符号名称。我所知道的是预处理没有类型安全、范围的概念。 这样做的真正好处是什么? #def
将 Singleton 实例声明为 static 还是声明为 static final 更好? 请看下面的例子: 静态版本 public class Singleton { private s
问题: 我观察到的行为是 TypeScript 的预期行为吗? 我观察到的行为是 ECMAScript 6 的预期行为吗? 是否有一种简单的方法可以返回继承层次结构以处理每个级别的“myStatic”
在php中,访问类的方法/变量有两种方法: 1. 创建对象$object = new Class(),然后使用”->”调用:$object->attribute/functi
我尝试向 ExpandoObject 添加一个动态方法,该方法会返回属性(动态添加)给它,但它总是给我错误。 我在这里做错了吗? using System; using System.Collecti
我试图获得一个静态链接到我的程序的音频库。我用 this灵活的包。为了让它运行,我必须按照描述构建 soloud 库 here .下载后不久,我在“build”文件夹中运行了“genie --with
这是我的webpack.prod.config.js代码 const path = require('path'); const { CleanWebpackPlugin } = require('c
我想知道什么时候应该对变量和(或)方法使用静态、最终、静态最终参数。据我了解: final:类似于c++中的const参数。它基本上意味着值(或在方法中 - 返回值)不会改变。 静态:这意味着值(或方
我一直在阅读有关使用静态对象作为锁的内容,最常见的示例如下: public class MyClass1 { private static final Object lock = new Obje
在 Visual Basic 2008 中,我知道有两种不同的方法可以完成同一件事: 成员(member)级别的 Dim: Dim counter1 as integer = 0 Dim counte
static public final int i = 0; public static final int i = 0; 两者都工作正常。 为什么同样的事情可以用两种不同的风格来完成? 最佳答案 因
我是一名优秀的程序员,十分优秀!