Ограничивает специализации с использованием SFINAE, Constraints или Concepts?

Следующая программа работает нормально:

struct M; // forward declare so compiler will recognize this type
struct N;

template< typename J > struct B { template< typename U > void Func1(); };

template<> template<> void B< M >::Func1< M >() {}
template<> template<> void B< N >::Func1< N >() {}
template<> template<> void B< M >::Func1< N >() {} // illegal specialization for this app

template< typename J > struct C { template< typename U > void Func2(); };

template<> template<> void C< M >::Func2< M >() {}
template<> template<> void C< N >::Func2< N >() {}

template< typename G > struct H { G g; };

int main()
{
  H< B< M > > hbm;
  hbm.g.Func1< M >(); // ok
  hbm.g.Func1< N >(); // compiles and runs, but uses a semantically illegal specialization for this app

  H< B< N > > hbn;
  hbn.g.Func1< N >(); // ok

  H< C< M > > hcm;
  hcm.g.Func2< M >(); // ok

  H< C< N > > hcn;
  hcn.g.Func2< N >(); // ok

  return 0;
}

Важно, чтобы структуры B и C были объявлены явно во время компиляции и чтобы были разрешены только те специализации, которые имеют смысл для приложения.

Но, как видно из приведенного выше кода, возможно, что мои нижестоящие разработчики (когда-нибудь!) Смогут создавать синтаксически правильные шаблоны, которые не имеют смысла семантически. В частности, приложение знает только то, как использовать типы, чьи типы классов и функций равны. Остальные бессмысленны.

Это похоже на случай с одной из новых возможностей C++17+, таких как SFINAE, Constraints или Concepts. Хотя я читаю их, у меня пока нет решения сделать такой выбор. В разделе "Альтернативы" они предлагают Concepts вместо SFINAE, если компилятор способен (я использую VS2015).

Что может быть хорошим способом ограничить typename J тем же, что и typename U?

1 ответ

Решение

Вы можете использовать enable_if:

template< typename J > struct B {     
    template<typename U>
    typename std::enable_if<std::is_same<U, J>::value, void>::type
    Func1();
};

http://coliru.stacked-crooked.com/a/efb499cf654f0f25

С концепциями (не стандартными в ближайшем (?) Будущем) то же решение, что и выше, будет выглядеть так, как показано ниже.

http://melpon.org/wandbox/permlink/li4Uh5Q6ilpnlhcl

template <class T, class U> concept bool Same = std::is_same<T,U>::value;

template< typename J > struct B { 
    template< typename U > 
    requires Same<J, U>    
    void Func1(); 
};
Другие вопросы по тегам