这个问题需要了解C ++模板元编程,因为它涉及(间接)表达模板。我间接地说,因为它不直接是关于表达模板的问题,而是涉及C ++类型的计算。如果您不知道那是什么,请不要回答这个问题。
为了避免在没有足够背景信息的情况下提出问题,请让我详细说明我要解决的一般问题,然后转到更具体的部分。
假设您有一个提供Integer
的库,用户可以像int
一样进行计算。
此外,可以从Integer
构造int
。就像:
Integer<int> i(2);
我的Integer
类内部是一个类模板:
template<class T>
class Integer {
// cut out
};
所以我可以在我喜欢的任何整数类型上定义它。
现在,在不更改API的情况下,我想更改库,如果Integer
是从int
构建的,则应该在内部用不同的类型表示,例如{{1} }。这样做的原因是我可以加快一些计算,因为知道IntegerLit
的实例是从Integer
创建的(可以将它作为int
参数传递给函数而不是作为一般对象由基指针+单独的数据描述。这只是一个注释。)
从int
构造时,类型不同是至关重要的,因为我需要编译器根据是从int
构造还是构建不同的代码路径不。我无法使用运行时数据标志执行此操作。 (原因很简单:编译器根据类型生成一个函数,它接受int
或上面提到的更一般类型的对象。)
有了这个说我遇到了一个问题:当用途做这样的事情时:
int
此处Integer<int> a,b(2);
a = b + b;
应为常规a
和Integer
专用b
。但是,我的问题是如何在C ++中表达这一点,因为用户可以自由地使用相同的类型IntegerLit
来定义她的变量。
使类型具有多态性,即从Integer
派生IntegerLit
将不起作用。它看起来很好。但是,由于用户创建的Integer
(基类)实例不起作用,因为它是基类,编译器会将其粘贴到表达式树中(这就是问题中涉及表达式模板的原因)。因此,两种情况之间不可能有任何区别。在这一点上做RTTI检查动态转换真的不是我想要的。
更有希望似乎是在类型中添加文字模板参数Integer
,说明它是否是从bool lit
构建的。关键是不要为一个非文字指定转换规则,而是为另一个案例指定转换规则。
然而,我无法让它发挥作用。如果不是从int
构造,则以下代码仅编译(GCC 4.7 C ++ 11)。否则会失败,因为未使用int
指定整数作为true
的值。因此编译器会搜索没有转换规则的默认实现。在从lit
构建时,不能更改API并要求编写Integer<int,true>
。
int
我开始想知道C ++是否可以这样做。
C ++ 11可能有新功能可以提供帮助吗?
答案 0 :(得分:5)
不,这不是C ++的工作原理。如果您将b
定义为Integer b
,那么它就是Integer
。无论后来用于初始化b
的表达式如何,这都适用。
另外,请考虑以下事项:extern Integer b;
。在其他地方有一个初始化b
的表达式,但编译器仍然必须在此处弄清楚b
的类型。 (不是“会有”,而是“有”)。
答案 1 :(得分:3)
无论如何,你无法做到这一点。 但是使用“自动”你可以接近。
// 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);
答案 2 :(得分:1)
你做不到。一旦你说变量是Integer<int>
这是变量的类型。你可以做的是让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
的类型相同,您也可以轻松地使用模板函数使其看起来表现为两种不同的类型(因为代码更改了有效类型)。 / p>