是否可以基于模板类型参数的嵌套typedef的存在来专门化模板定义? [英] Is it possible to specialize a template definition based on the existence of a nested typedef of a template type parameter?
问题描述
我有一个模板, template< typename T>类包装器
,我想专门化基于 typename T :: context_type
的存在。如果声明 typename T :: context_type
,则 wrapper
实例化的构造函数和赋值运算符重载应该接受强制的 typename T :: context_type
参数。另外, wrapper< T>
对象将在成员数据中存储上下文。如果 typename T :: context_type
不存在,则 wrapper< T>
的构造函数和赋值运算符重载将采用少一个参数,并且不会有其他数据成员。
这是否可能?我可以得到下面的代码来编译,而不改变 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不存在。 << std :: endl;
}
};
class config1 {
public:
typedef int context_type;
};
class config2 {
public:
};
int main()
{
wrapper< config1> w1(0);
wrapper< config2> w2;
}
我已经通过使用一些元编程技巧在过去实现这样的行为。基本构建块是:
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工作,类似这样的工作:
template< typename T,typename Context = void>
class wrapper {...}; //基本定义
template<类型名T>
class wrapper< T,typename voif_mfn < typename T :: context_type> :: type> {...}; // Specialization
然而,我喜欢基于traits的解决方案的表达能力, p>
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;
}
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:
template< typename T, typename Context = void >
class wrapper { ... }; // Base definition
template< typename T >
class wrapper< T, typename voif_mfn< typename T::context_type >::type > { ... }; // Specialization
However, I like the expressiveness of the solution based on traits and enable if.
这篇关于是否可以基于模板类型参数的嵌套typedef的存在来专门化模板定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!