static_assert<std::is_floating_point<T>::value, "") 由于未使用的模板类型而失败
static_assert<std::is_floating_point<T>::value, "") fails because of unused template types
我正在制作模板 Matrix
class,并且我已将模板参数限制为 integral 和 floating点数据类型
template class Matrix<int>;
template class Matrix<float>; ..etc
我实现了一个random()
静态成员函数,为了让它从0.0
到1.0
均匀随机分布,我用std::is_floating_point<T>
来限制使用浮动点类型的模板。我认为如果 T
不是浮点类型,static_assert
就会触发,但断言对于每个 template class Matrix<T>;
都失败,其中 T 是 整数 类型。
当我注释掉所有 integral 类型时,它工作正常,但我不能这样做,因为我需要能够使用 T
是 整数 类型。我该如何解决?
请注意,我为每个 integral/floating-point 类型提供了 template class Matrix<T>
,因为我得到 undefined reference
错误。所以我将初始化限制为 integral 和 floating 点类型。
// Matrix.cpp
template<typename T>
Matrix<T> Matrix<T>::rand(const size_t& r, const size_t& c) {
Matrix<T> result{ r, c };
static_assert(std::is_floating_point<T>::value,
"result_type must be a floating point type");
const float range_from = 0.0;
const float range_to = 1.0;
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_real_distribution<T> distr(range_from, range_to);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
result[i][j] = distr(generator);
}
}
return result;
}
//...
template class Matrix<int>;
template class Matrix<long>;
template class Matrix<float>;
template class Matrix<double>;
您有多种选择:
- 在 header 中提供(模板)代码而不是 cpp(参见 why-can-templates-only-be-implemented-in-the-header-file)
显式实例化方法而不是 class:
// all individual available methods of the class
template Matrix<int> Matrix<int>::other_method(/*..*/);
// ...
// Whole class
template class Matrix<float>;
template class Matrix<double>;
使用 SFINAE:
template<typename T>
class Matrix
{
template <typename U = T,
std::enable_if_t<std::is_same<T, U>::value
&& std::is_floating_point<U>::value, int> = 0>
Matrix<T> rand(const size_t &r, const size_t &c);
// ...
};
来自 C++20 的 或 requires
:
template<typename T>
class Matrix
{
Matrix<T> rand(const size_t &r, const size_t &c) requires (std::is_floating_point<T>::value);
// ...
};
或专攻class
template<typename T, typename Enabler = void>
class Matrix
{
// ...
};
template<typename T>
class Matrix<T, std::enable_if_t<std::is_floating_point<T>::value>>
{
Matrix<T> rand(const size_t &r, const size_t &c);
// ...
};
When I comment out all integral types, it works fine, but I can't do
this as I need to be able to make Matrix<T>
instances with T
is an
integral type. How would I fix it?
正如 @Jarod42 在评论中指出的那样,您可以应用 SFINAE 来限制 rand()
当且仅当模板类型是浮点数时函数。
额外说明:通过为特征中提到的允许类型有条件地实例化 class,可以应用相同的技术来限制 class Matrix<T>
的实例化。
以下是演示该想法的示例代码(使用 c++17 编译)。
(See online)
#include <iostream>
#include <type_traits> // for std::conjunction, std::negation, std::is_arithmetic, std::is_floating_point, std::enable_if
// traits for filtering out the allowed types
template<typename Type>
using is_allowed = std::conjunction<
std::is_arithmetic<Type>, // is equal to std::is_integral_v<T> || std::is_floating_point_v<T>>
std::negation<std::is_same<Type, bool>>, // negate the types which shouldn't be compiled
std::negation<std::is_same<Type, char>>,
std::negation<std::is_same<Type, char16_t>>,
std::negation<std::is_same<Type, char32_t>>,
std::negation<std::is_same<Type, wchar_t>>
>;
template<typename Type, typename ReType = void>
using is_allowed_type = std::enable_if_t<is_allowed<Type>::value, ReType>;
template<typename Type, typename Enable = void> class Matrix;
// conditional instantiation of the template class
template<typename Type> class Matrix<Type, is_allowed_type<Type>> /* final */
{
public:
template<typename T = Type>
std::enable_if_t<std::is_floating_point_v<T>, Matrix<T>> rand(const size_t& r, const size_t& c)
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SFINAE to restrict the use of rand()
{
Matrix<T> result{/*args*/};
// other code
return result;
}
};
template class Matrix<int>;
template class Matrix<long>;
template class Matrix<float>;
int main()
{
Matrix<double> obj;
obj.rand(1, 2);
}
我正在制作模板 Matrix
class,并且我已将模板参数限制为 integral 和 floating点数据类型
template class Matrix<int>;
template class Matrix<float>; ..etc
我实现了一个random()
静态成员函数,为了让它从0.0
到1.0
均匀随机分布,我用std::is_floating_point<T>
来限制使用浮动点类型的模板。我认为如果 T
不是浮点类型,static_assert
就会触发,但断言对于每个 template class Matrix<T>;
都失败,其中 T 是 整数 类型。
当我注释掉所有 integral 类型时,它工作正常,但我不能这样做,因为我需要能够使用 T
是 整数 类型。我该如何解决?
请注意,我为每个 integral/floating-point 类型提供了 template class Matrix<T>
,因为我得到 undefined reference
错误。所以我将初始化限制为 integral 和 floating 点类型。
// Matrix.cpp
template<typename T>
Matrix<T> Matrix<T>::rand(const size_t& r, const size_t& c) {
Matrix<T> result{ r, c };
static_assert(std::is_floating_point<T>::value,
"result_type must be a floating point type");
const float range_from = 0.0;
const float range_to = 1.0;
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_real_distribution<T> distr(range_from, range_to);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
result[i][j] = distr(generator);
}
}
return result;
}
//...
template class Matrix<int>;
template class Matrix<long>;
template class Matrix<float>;
template class Matrix<double>;
您有多种选择:
- 在 header 中提供(模板)代码而不是 cpp(参见 why-can-templates-only-be-implemented-in-the-header-file)
显式实例化方法而不是 class:
// all individual available methods of the class template Matrix<int> Matrix<int>::other_method(/*..*/); // ... // Whole class template class Matrix<float>; template class Matrix<double>;
使用 SFINAE:
template<typename T> class Matrix { template <typename U = T, std::enable_if_t<std::is_same<T, U>::value && std::is_floating_point<U>::value, int> = 0> Matrix<T> rand(const size_t &r, const size_t &c); // ... };
来自 C++20 的 或
requires
:template<typename T> class Matrix { Matrix<T> rand(const size_t &r, const size_t &c) requires (std::is_floating_point<T>::value); // ... };
或专攻class
template<typename T, typename Enabler = void> class Matrix { // ... }; template<typename T> class Matrix<T, std::enable_if_t<std::is_floating_point<T>::value>> { Matrix<T> rand(const size_t &r, const size_t &c); // ... };
When I comment out all integral types, it works fine, but I can't do this as I need to be able to make
Matrix<T>
instances withT
is an integral type. How would I fix it?
正如 @Jarod42 在评论中指出的那样,您可以应用 SFINAE 来限制 rand()
当且仅当模板类型是浮点数时函数。
额外说明:通过为特征中提到的允许类型有条件地实例化 class,可以应用相同的技术来限制 class Matrix<T>
的实例化。
以下是演示该想法的示例代码(使用 c++17 编译)。
(See online)
#include <iostream>
#include <type_traits> // for std::conjunction, std::negation, std::is_arithmetic, std::is_floating_point, std::enable_if
// traits for filtering out the allowed types
template<typename Type>
using is_allowed = std::conjunction<
std::is_arithmetic<Type>, // is equal to std::is_integral_v<T> || std::is_floating_point_v<T>>
std::negation<std::is_same<Type, bool>>, // negate the types which shouldn't be compiled
std::negation<std::is_same<Type, char>>,
std::negation<std::is_same<Type, char16_t>>,
std::negation<std::is_same<Type, char32_t>>,
std::negation<std::is_same<Type, wchar_t>>
>;
template<typename Type, typename ReType = void>
using is_allowed_type = std::enable_if_t<is_allowed<Type>::value, ReType>;
template<typename Type, typename Enable = void> class Matrix;
// conditional instantiation of the template class
template<typename Type> class Matrix<Type, is_allowed_type<Type>> /* final */
{
public:
template<typename T = Type>
std::enable_if_t<std::is_floating_point_v<T>, Matrix<T>> rand(const size_t& r, const size_t& c)
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SFINAE to restrict the use of rand()
{
Matrix<T> result{/*args*/};
// other code
return result;
}
};
template class Matrix<int>;
template class Matrix<long>;
template class Matrix<float>;
int main()
{
Matrix<double> obj;
obj.rand(1, 2);
}