您收到的具体错误是因为enable_if 采用 bool 作为第一个参数,但您向它传递了一个类型。
boost::is_complex<Scalar> // <- this is a type
要获取布尔值(true/false),您需要编写:
boost::is_complex<Scalar>::value // <- this is a bool value telling whether Scalar is complex
is_complex 结构继承自 true_type 或 false_type (取决于 Scalar 的类型),如果您想更详细地了解它是如何工作的,请查找它们;)
不过,您的代码还存在其他问题。 enable_if 需要依赖于调用函数时首先知道的模板参数,而不是类模板参数。你可以这样做:
template<typename Scalar>
class matrix
{
//...
public:
// print function that will be called for a matrix of complex numbers
template<typename T=Scalar
, typename std::enable_if<boost::is_complex<T>::value,int>::type = 0
>
void print() const;
// print function that will be called for a matrix of non-complex numbers
template<typename T=Scalar
, typename std::enable_if<!boost::is_complex<T>::value,int>::type = 0
>
void print() const;
//...
};
这将产生一个“开关”,根据类模板参数选择适当的类方法。按照惯例,我选择将enable_if 放在模板参数中,而不是放在函数签名中。我发现这是一个更通用的解决方案,并且更具可读性。
我不知道这是否是提供此功能的“最佳”方式(我无法想到任何主要缺点),但它会解决问题。希望能帮助到你 :)
编辑 2013 年 8 月 11 日:
我使用特定类型的enable_if结构,因为它允许我在两个函数之间进行enable_if切换,否则这两个函数将具有完全相同的签名。使用enable_if的“通常”方法之一是使用enable_if的结果作为模板参数的默认值,如下所示:
template<typename Scalar>
class matrix
{
//...
public:
// print function that will be called for a matrix of complex numbers
template<typename T=Scalar
, class = typename std::enable_if<boost::is_complex<T>::value>::type // enable_if is used to give default type for the class template
>
void print() const;
// print function that will be called for a matrix of non-complex numbers
template<typename T=Scalar
, class = typename std::enable_if<!boost::is_complex<T>::value>::type // same as above
>
void print() const; //<- this has same function signature as the above print()
// we get a compiler error
//...
};
编译器无法区分这两个打印函数,因为它们都以相同的方式模板化,并且具有相同的签名,因为它们都被视为
template<typename T, typename U>
void print() const;
在我的示例中,编译器不知道函数是如何模板化的,因为这是由enable_if的结果决定的
template<typename T, ?>
void print() const;
因此,当函数被调用并且enable_if被评估时,可以首先看到函数签名。按照惯例,我选择了 int,但你也可以使用 void*:
typename std::enable_if<!boost::is_complex<T>::value,void*>::type = nullptr
用 void* 代替 int,但不仅仅是 void,因为我们不能有 void 非类型模板参数。
为了完成您想做的事情,您需要在派生类中提供一个非模板化函数来覆盖基类中的抽象函数。为此你可以使用间接并做类似的事情:
class matrix_base
{
public:
virtual void print() const = 0;
};
template<typename Scalar>
class matrix: matrix_base
{
//...
private:
// print function that will be called for a matrix of complex numbers
template<typename T=Scalar
, typename std::enable_if<boost::is_complex<T>::value,int>::type = 0
>
void print_impl() const;
// print function that will be called for a matrix of non-complex numbers
template<typename T=Scalar
, typename std::enable_if<!boost::is_complex<T>::value,int>::type = 0
>
void print_impl() const;
public:
// print function that will override abstract print in base class
void print() const { print_impl(); } // <- redirect to one of the print_impl() functions
//...
};
这种方法的缺点是您需要为每种可能的矩阵类型提供 print_impl() 实现,即您不能只为复数提供 print_impl() 实现,还需要为非复数提供一个 print_impl() 实现。
希望这能让一些事情变得更清楚:)