根据模板参数有条件编译时包含/排除代码?
考虑以下类,其中内部结构 Y
用作类型,例如。在模板中,稍后:
template<int I>
class X{
template<class T1>
struct Y{};
template<class T1, class T2>
struct Y{};
};
现在,这个示例显然无法编译,并出现第二个 X::Y
已经定义或者模板参数太多的错误。
我想在没有(额外)部分专业化的情况下解决这个问题,因为 int I
参数不是唯一的参数,并且它的位置在不同的部分专业化中可能有所不同(我的实际结构看起来更像这样,上面只是为了简单起见),所以我希望一个类适合每个我的解决方案。
我的第一个想法显然是 enable_if
,但这对我来说似乎失败了,例如。我仍然遇到同样的错误:
// assuming C++11 support, else use boost
#include <type_traits>
template<int I>
class X{
template<class T1, class = std::enable_if<I==1>::type>
struct Y{};
template<class T1, class T2, class = std::enable_if<I==2>::type>
struct Y{};
};
因此,由于 enable_if
失败,我希望有另一种方法来实现以下编译时检查:
template<int I>
class X{
__include_if(I == 1){
template<class T1>
struct Y{};
}
__include_if(I == 2){
template<class T1, class T2>
struct Y{};
}
};
这只是为了节省我很多代码重复,但如果有可能的话我会非常高兴。
编辑:遗憾的是,我无法使用明显的:可变参数模板,因为我使用的是 Visual Studio 2010,因此我只能使用那里支持的 C++0x 内容。 :/
Consider the following class, with the inner struct Y
being used as a type, eg. in templates, later on:
template<int I>
class X{
template<class T1>
struct Y{};
template<class T1, class T2>
struct Y{};
};
Now, this example will obviously not compile, with the error that the second X<I>::Y
has already been defined or that it has too many template parameters.
I'd like to resolve that without (extra) partial specialization, since the int I
parameter isn't the only one and the position of it can differ in different partial specializations (my actual struct looks more like this, the above is just for simplicity of the question), so I'd like one class fits every I
solution.
My first thought was obviously enable_if
, but that seems to fail on me, eg. I still get the same errors:
// assuming C++11 support, else use boost
#include <type_traits>
template<int I>
class X{
template<class T1, class = std::enable_if<I==1>::type>
struct Y{};
template<class T1, class T2, class = std::enable_if<I==2>::type>
struct Y{};
};
So, since enable_if
fails, I hope there is another way to achieve the following compile time check:
template<int I>
class X{
__include_if(I == 1){
template<class T1>
struct Y{};
}
__include_if(I == 2){
template<class T1, class T2>
struct Y{};
}
};
It would just be to save me a lot of code duplication, but I'd be really happy if it was somehow possible.
Edit: Sadly, I can't use the obvious: variadic templates, as I'm using Visual Studio 2010, so only the C++0x stuff that is supported there I can use. :/
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这里有两个问题:
enable_if
适用于部分专业化,而不适用于主模板。回答 1.
正如您在聊天中所建议的,模板的链接列表可以模拟可变参数包。
如果您最终得到
next::next::next
垃圾,那么编写元函数或使用 Boost MPL 很容易。答案 2:
不同数量的模板可以类似地命名,但如果它们嵌套在 SFINAE 控制的类型中,它们仍然保持不同。
There are two problems here:
enable_if
works with partial specialization, not primary templates.Answer 1.
As you suggested in chat, a linked list of templates can emulate the variadic parameter pack.
If you end up with
next::next::next
garbage, it's easy to write a metafunction, or use Boost MPL.Answer 2.
The different-arity templates can be named similarly but still stay distinct if they are nested inside the SFINAE-controlled type.
给你:
http://ideone.com/AdEfl
代码:
说明:基本上它是部分特化的想法,但不同之处在于,不是在
Test
内专门化,而是委托给可以单独专门化于I
的特定类。这样,您只需为每个I
定义inner
版本一次。然后Test
的多个特化可以重用。inner
持有者用于使Test
类中的typedef
更易于处理。编辑:这是一个测试用例,显示如果传入错误数量的模板参数会发生什么: http://ideone.com /QzgNP
Here you go:
http://ideone.com/AdEfl
And the code:
Explanation: Basically it's an extension of the idea of partial specialization, however the difference is that rather than specializing within
Test
, delegate to a specific class that can be specialized onI
alone. That way you only need to define versions ofinner
for eachI
once. Then multiple specializations ofTest
can re-use. Theinner
holder is used to make thetypedef
in theTest
class easier to handle.EDIT: here is a test case that shows what happens if you pass in the wrong number of template arguments: http://ideone.com/QzgNP
你可以尝试下面(这不是部分专业化):
我怀疑答案是否那么简单!
编辑(模拟部分专业化):
@Xeo,我能够编译以下代码并且似乎很充实。
然而,在这里您可以使用 X<1>、X<2> 等。可以互换。但在你提到的更广泛的例子中,这是无关紧要的。不过,如果需要,您可以检查
I = 1
和I = 2
。Can you try below (it is not partial specialization):
I doubt if the answer is that simple !!
Edit (Mocking Partial specialization):
@Xeo, I was able to compile following code and seems to be fullfilling.
Here, however you can use X<1>, X<2> interchangeably. But in the broader example you mentioned, that is irrelevant. Still if you need, you can put checks for
I = 1
andI = 2
.这种方法怎么样 - http://sergey-miryanov.blogspot。 com/2009/03/template-class-overriding.html? (抱歉俄语)
How about this approach - http://sergey-miryanov.blogspot.com/2009/03/template-class-overriding.html? (sorry for russian)
您可以使用元函数(此处:内联
boost::mpl::if_c
,但可以任意复杂)来选择您想要的函数。不过,您需要一些脚手架才能使用构造函数:如果为每个 X 实例化两个
YforIeq
N 时出现问题,那么您可以尝试将它们包装为 nullary元函数(沿mpl::apply
的方式执行的操作)并使用mpl::eval_if_c
。You can use a meta function (here: inlined
boost::mpl::if_c
, but could be arbitrarily complex) to select the one you want. You need some scaffolding to be able to use constructors, though:If there's a problem with both
YforIeq
N being instantiated for each X, then you can try wrapping them as a nullary meta function (something along the waympl::apply
does) and usempl::eval_if_c
.