[英]Template class and 'invalid use of incomplete type' error
我有一个模板Matrix
class 并且我使用std::vector<std::vector<T>>
来存储数据。 我需要专门针对std::complex
矩阵的一些方法,例如:
template <typename T>
bool Matrix<T>::is_hermitian() const
{
if (!(*this).is_squared())
return false;
for (int r = 0; r < rows_; r++)
for (int c = 0; c < columns_; c++)
if (mat[r][c] != mat[c][r])
return false;
return true;
}
对于专门的方法,我认为是这样的:
template <typename T>
bool Matrix<std::complex<T> >::is_hermitian() const
{
if (!(*this).is_squared())
return false;
for (int r = 0; r < rows_; r++)
for (int c = 0; c < columns_; c++)
if (mat[r][c] != std::conj(mat[c][r]))
return false;
return true;
}
但是编译器给我一个错误
'invalid use of incomplete type'
我在.cpp
文件的末尾实例化了一堆 class ,我可以在主程序中使用它们:
template class Matrix<int>;
template class Matrix<double>;
template class Matrix<float>;
template class Matrix< std::complex<float> >;
template class Matrix< std::complex<int> >;
如何为所有std::complex<T>
类型实现一种方法?
如果您知道如何用Matrix< std::complex<T> >
替换最后两个实例,我将非常感激。
您不能部分专门化 function 模板,但可以 class 模板。 一个技巧是让成员 function 委托给助手 class 模板。 像这样的东西:
template <typename T>
struct IsHermitianHelper;
template <typename T>
class Matrix {
friend class IsHermitianHelper<T>;
public:
bool is_hermitian() const;
};
template <typename T>
struct IsHermitianHelper {
static bool is_hermitian(const Matrix<T>& m) {
// General implementation here
}
};
template <typename T>
struct IsHermitianHelper<std::complex<T>> {
static bool is_hermitian(const Matrix<std::complex<T>>& m) {
// Special case for std::complex here
}
};
template <typename T>
bool Matrix<T>::is_hermitian() const {
return IsHermitianHelper<T>::is_hermitian(*this);
}
当T
是Matrix<T>
class instatiation 中的std::complex
时,您可以应用 SFINE(即“替换失败不是错误” )技术以及 function 重载来选择正确的方法。
下面是这个想法的演示:(见示例代码在线直播)
#include <type_traits> // std::enable_if, std::false_type
// traits for checking, T is `std::complex`
template<typename> struct is_std_complex : std::false_type {};
template<typename T> struct is_std_complex<std::complex<T>> : std::true_type {};
// traits for `std::enable_if` helpers
template<typename Type, typename ReType = void>
using EnabledForComplex = typename std::enable_if<is_std_complex<Type>::value, ReType>::type;
template<typename Type, typename ReType = void>
using EnabledNotForComplex = typename std::enable_if<!is_std_complex<Type>::value, ReType>::type;
template<typename T>
class Matrix
{
// ...members
public:
template<typename Type = T>
auto is_hermitian() const -> EnabledNotForComplex<Type, bool>
{
// ... code for non-std::complex types
}
template<typename Type = T>
auto is_hermitian() const->EnabledForComplex<Type, bool>
{
// ... code for std::complex types
}
};
话虽这么说,如果您有权访问c++17 ,则可以使用if constexpr
,它只会实例化分支,这对于编译时的情况是正确的。 (在线查看示例代码)
#include <type_traits> // std::false_type
// traits for checking, T is `std::complex`
template<typename> struct is_std_complex : std::false_type {};
template<typename T> struct is_std_complex<std::complex<T>> : std::true_type {};
template<typename T>
class Matrix
{
// ...members
public:
bool is_hermitian() const
{
if (!is_squared()) return false;
if constexpr (is_std_complex<T>::value)
{
// ... code for std::complex types
}
else
{
// ... code for non-std::complex types
}
return true;
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.