0

How to restrict a template argument of Wrapper to be a Wrapper<Any,MyArray<AnyT>> elegantly?

  1. Don't break content assist (Visual Studio).
  2. High readability. Not use a hacky approach.
    For some reasons, most solution love to hack.
  3. 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 :-

0

1 Answer 1

1

You can write a custom type trait is_specialization, as follows:

template<class Type, template<class...> class Template> struct is_specialization : std::false_type {}; template<template<class...> class Template, class... TArgs> struct is_specialization<Template<TArgs...>, Template> : std::true_type {}; 

Then you just need to static_assert that is_specialization is true for the given template argument:

template<class T,class T2> class Wrapper { static_assert(is_specialization<T2, MyArray>::value, "T2 must be a specialization of MyArray"); }; 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.