How to restrict a template argument of Wrapper to be a Wrapper<Any,MyArray<AnyT>> elegantly?
- Don't break content assist (Visual Studio).
- High readability. Not use a hacky approach.
For some reasons, most solution love to hack. - Make it obvious at the very first line by using C++ syntax rule. (not just green comment)
As far as I know, there are many solutions, but every solution doesn't meet the criteria.
Workaround 1 (template specialization, fail 1)
template<class T> class MyArray{}; template<class T,class T2> class Wrapper; template<class T,class T2> class Wrapper<T,MyArray<T2>>{ using Test=int; }; class B{}; class C{}; int main() { Wrapper<C,MyArray<B>> wrapper; return 0; } This code is modified from https://stackoverflow.com/a/43518221 (@max66).
Context clue / syntax highlighting of IDE will be confused.
In my case, it marks some correct types as error e.g. :-
class ShowError : public Wrapper<B,MyArray<C>>{ Test n=0; //<-- unknown "Test" (intellisense) }; Workaround 2 (some hacky field/typedef, fail 2)
template<class T> class MyArray{ public: using MyArrayT=T; }; template<class T,class T2> class Wrapper{ public: using myT=typename T2::MyArrayT; //^ assert at compile time }; This idea come from a comment in https://stackoverflow.com/a/43518295 (@Jarod42)
The class declaration doesn't mention about MyArray, it just uses a hacky (less readable) way (MyArrayT) to enforce that T2 is MyArray.
Workaround 3 (base class, fail 2)
class MyArrayBase{}; template<class T> class MyArray : public MyArrayBase{ }; template<class T,class T2> class Wrapper{ //check something around MyArrayBase *object = new T2(); // or "is_base_of" }; The code is modified from Restrict C++ Template Parameter to Subclass and C++ templates that accept only certain types.
It has same disadvantage as workaround 2.
It is not obvious for common user.
Workaround 4 (SNIFAE, fail 1)
By adding std::enable_if on the template class declaration (Wrapper), I can get a working hack.
Unfortunately, content assist hate it.
Reference
Here are the other links that I read :-
- http://www.informit.com/articles/article.aspx?p=376878 (template template parameter)
- restrict a template function, to only allow certain types (not related to template type as a parameter)