仅使用 bool 和 char 定义一个 templete 类



我打算有一个只专门处理布尔或字符类型的类,而不使用boost。我的代码如下,我正在使用VS2017社区:

#include <type_traits>
template<typename T,
    typename std::enable_if_t< 
    std::is_same<T, bool>::value || std::is_same<T, char>::value >::type >
class BoolAndCharData
{
public:
    BoolAndCharData(const T& _data) {...}
    void DoSomething() {...}
}; // end of class BoolAndCharData

int main()
{
char c;
BoolAndCharData<char> data(c); //  error C2976: too few template parameter
....
} // end of main()

我尝试了另一种方式,因为有人在这个网站上介绍,编译器说它无法识别模板:

template<typename T>
class BoolAndCharData<T, 
    typename std::enable_if_t< std::is_same<T, bool>::value || 
    std::is_same<T, char>::value >::type >
{
public:
    BoolAndCharData(const T& _data) {...}
    void DoSomething() {...}
}; // end of class BoolAndCharData

我已经浏览了这个网站和其他网站几个小时,发现虽然有很多关于限制模板类型的讨论,但大多数要么使用boots,要么特定于某个功能。我仍然不清楚如何使用选定的数据类型编写模板类。有人可以指出方法将我从盲目尝试中解救出来吗?

你不需要

使用 std::enable_if_t 来做到这一点。在这种情况下,static_assert就足够了。
举一个最小的工作示例:

#include <type_traits>
template<typename T>
class BoolAndCharData {
    static_assert(std::is_same<T, bool>::value or std::is_same<T, char>::value, "!");
public:
    BoolAndCharData(const T& _data) {}
    void DoSomething() {}
};
int main() {
    char c;
    BoolAndCharData<char> d1(c);
    // the following line won't compile
    // BoolAndCharData<int> d2(0);
    // ...
}

在科利鲁看到它。使用static_assert时的错误也比通常从模板中得到的错误更好。

可能的解决方案如下

template <typename, typename = void>
class BoolAndCharData;
template <typename T>
class BoolAndCharData<T, std::enable_if_t< 
   std::is_same<T, bool>::value || std::is_same<T, char>::value > >
 {
   public:
      BoolAndCharData(const T& _data)
       {}
      void DoSomething()
       {}
 };

主题的一点变化是定义特定的类型特征

template <typename, typename = void>
struct boolOrChar
 { };
template <typename T>
struct boolOrChar<bool, T>
 { using type = T; };
template <typename T>
struct boolOrChar<char, T>
 { using type = T; };

所以BoolAndCharData可以写成

template <typename, typename = void>
class BoolAndCharData;
template <typename T>
class BoolAndCharData<T, typename boolOrChar<T>::type>
 {
   public:
      BoolAndCharData(const T& _data)
       {}
      void DoSomething()
       {}
 };

您可以使用模板专用化以及通用代码的继承:

// Declares the generic case
template<typename T>
struct BoolAndCharData;
// Common base-class for the common code
template<typename T>
struct BoolAndCharDataCommon
{
    explicit BoolAndCharDataCommon(T) {}
    void DoSomething() {}
};
// Specialization for the char data-type
template<>
struct BoolAndCharData<char> : public BoolAndCharDataCommon<char>
{
    // To use the constructor(s) from the base class
    using BoolAndCharDataCommon::BoolAndCharDataCommon;
};
// Specialization for the bool data-type
template<>
struct BoolAndCharData<bool> : public BoolAndCharDataCommon<bool>
{
    // To use the constructor(s) from the base class
    using BoolAndCharDataCommon::BoolAndCharDataCommon;
};
int main()
{
    BoolAndCharData<char> a('a');
    BoolAndCharData<bool> b(false);
    a.DoSomething();
    b.DoSomething();
    // This will lead to a compiler error
    BoolAndCharData<int> c;
}

这种方式可以轻松收集所有通用代码,但如果需要,也很容易添加特定于特定类型的代码。

相关内容

  • 没有找到相关文章

最新更新