让编译器做出最终选择,要使用哪种类型
Let the compiler make the final choice which type to use
这个问题需要了解C 模板元编程,因为(间接)表达模板。我间接地说,因为它不是直接的表达模板问题,而是涉及C 类型的计算。如果您不知道是什么,请不要回答这个问题。
避免在没有足够背景信息的情况下提出问题,让我详细介绍我要解决的一般问题,然后转到更具体的部分。
假设您有一个提供Integer
s的库,用户可以像int
s一样进行计算。此外,可以从int
构建Integer
。就像:
Integer<int> i(2);
内部我的Integer
类是类模板:
template<class T>
class Integer {
// cut out
};
所以我可以在我喜欢的任何整数类型上定义它。
现在没有更改API,我想以一种从int
构造的Integer
来更改库,应该在内部以其他类型表示IntegerLit
。原因是我知道Integer
的实例是从int
创建的(可以将其作为int
参数传递到函数,而不是基本指针 单独的数据描述的一般对象。就像评论一样。)
从int
构造时,类型是不同的,因为我需要编译器根据int
构造是否构建编译器来操作不同的代码路径。我无法使用运行时数据标志来执行此操作。(简而言之:编译器生成一个函数,该函数取决于int
或上述更通用的对象类型。)
这样说我会遇到一个问题:当用途这样做时:
Integer<int> a,b(2);
a = b + b;
这里a
应该是一般Integer
和b
专用IntegerLit
。但是,我的问题是如何在用户免费使用相同类型的Integer
定义她的变量时表达C 。
制作类型的多态性,即从Integer
派生IntegerLit
行不通。片刻看起来不错。但是,由于用户创建了Integer
(基类)的实例,因为它是编译器粘在表达树中的基类,因此无法使用(这就是为什么表达模板都参与问题的原因)。因此,在两种情况之间不可能区分。做RTTI检查LA动态演员真的不是我想要的。
更有前途的似乎是在类型上添加了字面模板参数bool lit
,说明它是由int
构造的。关键是不要为一个不是字面的转换规则指定转换规则,而是为另一种情况指定。
但是,我无法做到这一点。如果不从int
构造,则仅编译以下代码(GCC 4.7 C 11)。否则,它会失败,因为整数未用true
指定为lit
的值。因此,编译器搜索没有转换规则的默认实现。从int
构造时,它不是更改API的选项,需要编写Integer<int,true>
。
template<class T,bool lit=false>
class Integer
{
public:
Integer() {
std::cout << __PRETTY_FUNCTION__ << "n";
}
T F;
};
template<>
template<class T>
class Integer<T,true>
{
public:
Integer(int i) {
std::cout << __PRETTY_FUNCTION__ << "n";
}
T F;
};
我开始想知道C 是否可以使用类似的事情。
可能有C 11的新功能可以在这里提供帮助?
不,这不是C 的工作方式。如果将b
定义为Integer b
,则是Integer
。这适用于随后用于初始化b
的表达式。
另外,请考虑以下内容:extern Integer b;
。在其他地方有一个表达式,可以初始化b
,但是编译器仍然必须在这里弄清楚哪种类型b
具有。(不是"有",而是"有")。
您完全无法做到这一点。但是使用"自动"可以接近。
// The default case
Integer<int> MakeInt()
{
return Integer<int>();
}
// The generic case
template <class T>
Integer<T> MakeInt(T n)
{
return Integer<T>(n);
}
// And specific to "int"
Integer<IntegerLit> MakeInt(int n)
{
return Integer<IntegerLit>(n);
}
auto a = MakeInt();
auto b = MakeInt(2);
auto c = MakeInt('c');
auto d = MakeInt(2.5);
您不能做到这一点。一旦您说一个变量是Integer<int>
,即变量类型。您的 can 是使Integer
的基础代表因使用哪个构造函数而有所不同,类似的是:
template<class T>
class Integer {
// cut out
Integer() : rep_(IntRep()) {}
explicit Integer(int val) : rep_(IntLitRep(val)) {}
private:
boost::variant<IntRep, IntLitRep> rep_;
};
然后,您可以轻松地确定哪种变体版本是活动的,并在需要时使用不同的代码路径。
编辑:在这种情况下,即使Integer
的类型相同,您也可以轻松地使用模板函数使其看起来像是两种单独的类型(因为REP更改有效类型)。
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 任何种类的分数 在任何类型的订单中
- 2 种模板相关类型种类的差异
- C++每帧更新和复制一系列值.我应该使用哪种类类型
- 在键上使用 map.find() 和 count(),这是一种类对象类型