简体   繁体   English

模板:类专业化

[英]Template : class specialization

I'm new in the C++ world.我是 C++ 世界的新手。 Sorry for my nooby question.抱歉我的菜鸟问题。

I have a class我有一堂课

template <typename T>
class Foo
{
  T t_;
  void say_hello() 
  { std::cout << "Ciao";}
  // work with T ...
};

I want to specialize this template class for 3 types.我想将此模板类专门用于 3 种类型。

If type is ( A or B or C ), Then use this class如果类型是( ABC ),则使用此类

template<>
class Foo<A or B or C>
{
  void say_hello() 
  { std::cout << "Hello";}
};

What's the best way to do this?做到这一点的最佳方法是什么? Thank you for your help.感谢您的帮助。

A possible solution uses SFINAE一种可能的解决方案使用 SFINAE

template <typename T, typename = void>
class Foo
{
  T t_;
  void say_hello() 
  { std::cout << "Ciao";}
  // work with T ...
};

template <typename T>
class Foo<T, std::enable_if_t<std::is_same_v<T, A>,
                           || std::is_same_v<T, B>,
                           || std::is_same_v<T, C>>
{
  void say_hello() 
  { std::cout << "Hello";}
};

If you don't use T inside the Foo specialization (as in your example) you can also use a sort of self-inheritance如果您不在Foo专业化中使用T (如您的示例中所示),您还可以使用一种自我继承

template <typename T>
class Foo
{
  T t_;
  void say_hello() 
  { std::cout << "Ciao";}
  // work with T ...
};

template <>
class Foo<A>
{
  void say_hello() 
  { std::cout << "Hello";}
};

template <>
class Foo<B> : public Foo<A>
 { };

template <>
class Foo<C> : public Foo<A>
 { };

Off Topic: if you want to use say_hello() outside the class, is better if you make it public (or if you declare Foo as a struct ).题外话:如果你想在课堂外使用say_hello() ,最好将它public (或者如果你将Foo声明为struct )。

There are several possibilities, for example:有几种可能,例如:

Specialization of the method only:仅该方法的专业化:

template<>
void Foo<A>::say_hello() { std::cout << "Hello"; }
template<>
void Foo<B>::say_hello() { std::cout << "Hello"; }
template<>
void Foo<C>::say_hello() { std::cout << "Hello"; }

or, in C++17, you might do:或者,在 C++17 中,你可以这样做:

template <typename T>
class Foo
{
  T t_;
  void say_hello() 
  {
      if constexpr(std::is_same_v<T, A> || std::is_same_v<T, B> || std::is_same_v<T, C>) {
          std::cout << "Hello";
      } else {
          std::cout << "Ciao";
      }
  }
  // work with T ...
};

Whereas regular if works in that example, it would fail if you call code specific to A , B , C .虽然常规if在该示例中有效,但如果您调用特定于ABC代码,它将失败。 if constexpr won't have that issue. if constexpr不会有这个问题。

A variant of the SFINAE solution that is a bit more concise for more classes. SFINAE 解决方案的一种变体,对于更多类来说更简洁一些。

template<class T, class... Ts>
struct is_one_of;

template<class T, class Ts>
struct is_one_of<T, T, Ts...> : std::true_type {}; //maybe add std::decay_t

template<class T, class S, class Ts>
struct is_one_of<T, S, Ts...> : is_one_of<T, Ts...> {};

template<class T>
struct is_one_of<T> : std::false_type{};

template<class T, class... Ts>
constexpr bool is_one_of_v = is_one_of<T, Ts...>::value;

template <typename T, typename = void>
class Foo
{
  T t_;
  void say_hello() 
  { std::cout << "Ciao";}
  // work with T ...
};

template <typename T>
class Foo<T, std::enable_if_t<is_one_of_v<T, A, B, C>
{
  void say_hello() 
  { std::cout << "Hello";}
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM