【问题标题】:Type checking template class parameters类型检查模板类参数
【发布时间】:2013-10-13 15:14:18
【问题描述】:

我试图通过禁止隐式类型转换(例如 string->bool)来实现模板类参数的类型检查,从而引发编译错误。 具体场景很简单,如下:

#include <iostream>
#include <string>
using namespace std;

template <class T>
class myPair {
T a, b;
public:
  myPair(T first, T second ) {
  a = first;
  b = second;
  }
  void test();
};

typedef myPair<bool> boolParm;

template<class T>
void myPair<T>::test() {
  if(a == true) {
  cout << "a is true" << endl;
  } else {
  cout << "a is false" << endl;   
  }
  if(b == true) {
  cout << "b is true" << endl;
  } else {
  cout << "b is false" << endl;
  }
}

int main() {
  boolParm myObj(false, "false");
  myObj.test();
  return 0;
}

上述场景的输出是不可取的,因为用户可能无意中传递了 2 种不同的类型:bool 和 string,并将第一个接收为 false(正确,因为传递为 bool)但第二个将是 true(不正确,因为隐式类型从字符串到布尔值的转换)。 我希望限制 main() 中的用户代码引发编译错误并禁止字符串/int 参数传入构造函数。它应该只允许布尔。 我尝试使用重载的构造函数 myPair(bool first, string second) 但它不匹配,因为我猜 string->bool 的隐式类型转换发生在调用构造函数之前。 在这种情况下是否有使用模板专业化的解决方案? 非常感谢任何帮助 谢谢

【问题讨论】:

    标签: c++ templates typechecking


    【解决方案1】:

    一种解决方法是添加一个模板化工厂函数来创建 myPair。

    template <typename T>
    myPair<T> makeParam(T a, T b) {
        return myPair<T>(a, b);
    }
    

    如果类型不匹配,则使用模棱两可的模板参数 T 将无法编译。您可以使用模板特化来扩展它,明确禁止 T 的某些类型。您的 main 函数将如下所示:

    int main() {
        boolParm myObj = makeParam(false, "false");
        myObj.test();
        return 0;
    }
    

    或者改变构造函数:

    template <typename U, typename V>
    myPair(U a, V b);
    

    并根据需要进行专业化

    这种专业化的一个例子:

    template <class T>
    class myPair {
        T a, b;
    public:
        template <typename U, typename V> // generic version
        myPair(U first, V second)
        {
            // intentionally fail to compile
            static_assert(false, "don't support generic types");
        }
    
        template <> // template specialization
        myPair(T first, T second)
        {
            // explicitly require exactly type T
            a = first;
            b = second;
        }
    };
    

    【讨论】:

    • 啊因为这里是模板解析失败而不是参数转换!巧妙!
    • 感谢 cmets...我的问题是 main() 中的部分是用户代码,我不能要求用户更改他们的代码或以上述格式支持已经编写的用户代码。 .我只能在基类中进行修改,即 myPair 来实现这个功能。
    • @gigaplex:您能否再提一些关于如何在这种情况下使用专业化的细节,正如您在第二个选项中提到的那样!
    • 我在我的答案中添加了一个模板专业化的例子
    • @gigaplex:谢谢你的例子。但是我对如何使用模板专业化有点困惑。像,以下编译失败: [CODE] template class myPair { T a, b; public: myPair(T first, T second ); }; typedef myPair boolParm;模板 myPair::myPair(T first, T second) { a = first; b = 第二; } template myPair::myPair(T first, T1 second) { static_assert(false, "不支持泛型"); } [/CODE]
    【解决方案2】:

    乍一看确实很奇怪;但据我所知,您不能禁止这样做 - 无论如何,对于像 bool 这样的原始类型,您不能禁止。

    参数的隐式转换发生在您获得发言权之前,似乎存在从char const *bool 的隐式原始类型转换。

    参见例如另一个问题:Why does a quoted string match bool method signature before a std::string?

    【讨论】:

      猜你喜欢
      • 2012-11-18
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-18
      相关资源
      最近更新 更多