我很少遇到boost :: enable_if以及如何使用它进行构造函数切换。
代码是这样的:
struct NullType{};
struct TestType{};
struct NonNull{};
template<typename T, typename U = NullType>
struct TemplateStruct
{
TemplateStruct(int i, typename boost::enable_if<boost::is_same<U, NullType>, void* >::type dummy = 0)
{
std::cout << "One Param == " << i << std::endl;
}
TemplateStruct(int i, int j, typename boost::disable_if<boost::is_same<U, NullType>, void* >::type dummy = 0)
{
std::cout << "Two Param == " << i << "," << j << std::endl;
}
};
int main(int /*argc*/, char**)
{
TemplateStruct<TestType>(1);
TemplateStruct<TestType,NonNull>(1,2);
return 0;
}
我要归档的内容如下。它希望第一个Ctor仅在给出NullType时可用。在所有其他情况下,我想禁用第一个Ctor并启用第二个。
目前我收到编译错误,因为其中一个构造函数无效。但是,如何使Ctor成为模板化的并重用类模板参数?
答案 0 :(得分:3)
这是解决问题的一种方法:
template<typename T, typename U = NullType>
struct TemplateStruct
{
TemplateStruct(int i)
{
boost::enable_if< boost::is_same<U,NullType>, void*>::type var = nullptr;
std::cout << "One Param == " << i << std::endl;
}
TemplateStruct(int i, int j)
{
boost::disable_if< boost::is_same<U,NullType>, void*>::type var = nullptr;
std::cout << "Two Param == " << i << "," << j << std::endl;
}
};
int main()
{
TemplateStruct<TestType>(1);
TemplateStruct<TestType,NonNull>(1,2);
//will not compile TemplateStruct<TestType>(1,2);
//will not compile TemplateStruct<TestType,NonNull>(1);
}
EDIT1:或者假设您选择的编译器和您使用的STL实现支持static_assert和类型特征(即VS 2010),如果尝试使用已禁用的ctor,您可以获得更好的错误消息:
template<typename T, typename U = NullType>
struct TemplateStruct
{
TemplateStruct(int i)
{
static_assert( std::is_same<U,NullType>::value, "Cannot use one parameter ctor if U is NullType!" );
std::cout << "One Param == " << i << std::endl;
}
TemplateStruct(int i, int j)
{
static_assert( !std::is_same<U,NullType>::value, "Cannot use two parameter ctor if U is not NullType!" );
std::cout << "Two Param == " << i << "," << j << std::endl;
}
};
EDIT2:或者如果您的STL中没有is_same,但您有static_assert:
template<typename T, typename U = NullType>
struct TemplateStruct
{
TemplateStruct(int i)
{
static_assert( boost::is_same<U,NullType>::value, "Cannot use one parameter ctor if U is NullType!" );
std::cout << "One Param == " << i << std::endl;
}
TemplateStruct(int i, int j)
{
static_assert( !boost::is_same<U,NullType>::value, "Cannot use two parameter ctor if U is not NullType!" );
std::cout << "Two Param == " << i << "," << j << std::endl;
}
};
答案 1 :(得分:1)
我不知道您确切问题的解决方案。
也许这段代码会有所帮助(注意你不需要enable_if机制)。至少它可以成为更好的解决方案的起点:
#include <iostream>
struct NullType{};
struct TestType{};
struct NonNull{};
template<typename T, typename U>
struct TemplateStruct
{
TemplateStruct(int i, int j)
{
std::cout << "Two Param == " << i << "," << j << std::endl;
}
};
template<typename T>
struct TemplateStruct<T, NullType>
{
TemplateStruct(int i)
{
std::cout << "One Param == " << i << std::endl;
}
};
int main(int /*argc*/, char**)
{
TemplateStruct<TestType,NullType>(1);
TemplateStruct<TestType,NonNull>(1,2);
return 0;
}
如果专门化TemplateStruct&lt;&gt;那将无效是不可取的/不可能的,或者你不想指定NullType。
关于你对代码膨胀的担忧,我怀疑它是否相关:只有实例化的东西才能获得目标代码。
答案 2 :(得分:0)
解决此问题的一种方法是在实际类周围使用一个小包装器,然后专门设计该包装器。如果您只想启用/禁用几个功能,这种方法很有效。
struct NullType{};
struct TestType{};
struct NonNull{};
template<typename T, typename U>
struct TemplateStruct
{
TemplateStruct(int i){
std::cout << "One Param == " << i << std::endl;
}
TemplateStruct(int i, int j){
std::cout << "Two Param == " << i << "," << j << std::endl;
}
void FunctionToDisableFor1Param(){
}
void FunctionToAlwaysEnable(){
}
};
template<class T, class U = NullType>
struct TSWrapper : public TemplateStruct<T,U>{
typedef TemplateStruct<T,U> BaseType;
TSWrapper(int i, int j)
: BaseType(i,j)
{}
};
template<class T>
struct TSWrapper<T,NullType> : public TemplateStruct<T,NullType>{
typedef TemplateStruct<T,NullType> BaseType;
TSWrapper(int i)
: BaseType(i)
{}
private:
using BaseType::FunctionToDisableFor1Param;
};
int main()
{
TSWrapper<TestType> x(1);
TSWrapper<TestType,NonNull> y(1,2);
x.FunctionToAlwaysEnable();
y.FunctionToDisableFor1Param();
// uncomment for compile time error
//x.FunctionToDisableFor1Param();
return 0;
}