How to enable constructor with mpl methods

I am a bit stuck in boost :: enable_if and how to make a constructor with it.

The code looks like this:

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; } 

I want to archive the following. He wants the first Ctor to be available only when issuing NullType. In all other cases, I want to disable the first Ctor and enable the second.

I am currently getting a compilation error because one of the constructors is invalid. But how can I make Ctor a template and reuse the class template parameter?

+4
source share
3 answers

This is one way to solve your problem on your own:

 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: If you assume that your select compiler and the STL implementation that you use support static_assert and type functions (e.g. VS 2010), you can get more efficient error messages if you try to use a disabled 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: Or, if your STL does not have is_same, but you have 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; } }; 
+3
source

I do not know the solution to your specific problem.

Perhaps this code will help (note that you do not need the enable_if mechanism for this). At the very least, this could be the starting point for a better solution:

 #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; } 

This will not work if the specialization TemplateStruct <> is undesirable / impossible or you do not want to specify NullType.

As for your concern about code bloat, I doubt it matters: only what was created gets into the object code.

+1
source

One way to resolve this issue is to have a small wrapper around the actual class and simply specialize this wrapper. This works well if you do not want to enable / disable several functions.

 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; } 
0
source

Source: https://habr.com/ru/post/1345672/


All Articles