是否可以根据模板类型参数的嵌套 typedef 的存在来专门化模板定义?
我有一个模板, template
,我想根据typename T::context_type
的存在进行专门化。如果声明了 typename T::context_type,则包装器实例化的构造函数和赋值运算符重载应接受强制的 typename T::context_type< /代码> 参数。此外,wrappertypename T::context_type
不存在,则 wrapper
的构造函数和赋值运算符重载将少一个参数,并且不会有额外的数据成员。
这可能吗?我可以在不更改 config1
、config2
和 main()
定义的情况下编译以下代码吗?
#include <iostream>
template <typename T, bool context_type_defined = true>
class wrapper
{
public:
typedef typename T::context_type context_type;
private:
context_type ctx;
public:
wrapper(context_type ctx_)
: ctx(ctx_)
{
std::cout << "T::context_type exists." << std::endl;
}
};
template <typename T>
class wrapper<T, false>
{
public:
wrapper() {
std::cout << "T::context_type does not exist." << std::endl;
}
};
class config1 {
public:
typedef int context_type;
};
class config2 {
public:
};
int main()
{
wrapper<config1> w1(0);
wrapper<config2> w2;
}
I have a template, template <typename T> class wrapper
, that I would like to specialize based on the existence of typename T::context_type
. If typename T::context_type
is declared, then the constructors and assignment operator overloads of the wrapper<T>
instantiation should accept a mandatory typename T::context_type
parameter. Additionally, wrapper<T>
objects would store "context" in the member data. If typename T::context_type
does not exist, then the constructors and assignment operator overloads of wrapper<T>
would take one less parameter and there would be no additional data member.
Is this possible? Can I get the following code to compile without changing the definitions of config1
, config2
, and main()
?
#include <iostream>
template <typename T, bool context_type_defined = true>
class wrapper
{
public:
typedef typename T::context_type context_type;
private:
context_type ctx;
public:
wrapper(context_type ctx_)
: ctx(ctx_)
{
std::cout << "T::context_type exists." << std::endl;
}
};
template <typename T>
class wrapper<T, false>
{
public:
wrapper() {
std::cout << "T::context_type does not exist." << std::endl;
}
};
class config1 {
public:
typedef int context_type;
};
class config2 {
public:
};
int main()
{
wrapper<config1> w1(0);
wrapper<config2> w2;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,这是可能的。我过去曾通过使用一些元编程技巧来实现这种行为。基本构建块是:
BOOST_MPL_HAS_XXX_TRAIT_DEF
,定义一个元函数谓词,如果参数是类类型并且具有给定名称的嵌套类型(在您的情况下为 context_type ),则该谓词将计算为真实类型。http://www .boost.org/doc/libs/1_47_0/libs/mpl/doc/refmanual/has-xxx-trait-def.html
Boost.EnableIf
,定义基于先前定义的特征的专业化。http://www.boost.org/libs/utility/enable_if.html # 请参阅 3.1 启用模板类专业化
请注意,您也许能够直接与 SFINAE 一起使用该行为,类似这样的操作可能会起作用:
但是,我喜欢基于特征和启用 if 的解决方案的表达能力。
Yes, it is possible. I have implemented such behavior in the past by using some metaprogramming tricks. The basic build blocks are:
BOOST_MPL_HAS_XXX_TRAIT_DEF
, to define a metafunction predicate that will evaluate to a true type if the argument is of class type and has a nested type with a given name (context_type in your case).http://www.boost.org/doc/libs/1_47_0/libs/mpl/doc/refmanual/has-xxx-trait-def.html
Boost.EnableIf
, to define the specializations based on the previously defined trait.http://www.boost.org/libs/utility/enable_if.html # See 3.1 Enabling template class specializations
Note that you may be able to get that behavior working directly with SFINAE, something like this may work:
However, I like the expressiveness of the solution based on traits and enable if.
这是可能的,并且有很多方法可以实现这一点。所有这些都应该返回到某个特征类
has_type
,以便如果成员 typedef 存在,则has_type::value
为 true,否则为 false。假设我们已经有了这个特质类别。那么这里有一个解决方案,使用 C++11 模板别名:现在进行 typetrait:
如果你没有 C++11,或者如果你不想重写整个类,你可以使区分更精细-grained,例如使用
std::enable_if
、std::conditional
等。如果您想要一些具体示例,请发表评论。That's possible, and there are many ways to implement this. All of them should go back on some trait class
has_type
so thathas_type<T>::value
is true if the member typedef exists, and false otherwise. Let's assume we have this trait class already. Then here's one solution, using C++11 template aliases:Now to make the typetrait:
If you don't have C++11, or if you don't want to rewrite the entire class, you can make the distinction more fine-grained, e.g. by using
std::enable_if
,std::conditional
, etc. Post a comment if you want some specific examples.使用 @K-ballo的回答,我写了以下内容:
现在,示例代码编译并输出:
Using @K-ballo's answer, I wrote the following:
Now, the sample code compiles and outputs: