C++ - 如何从具有 const 大小的算术类型数组创建 class 构造函数?
C++ - How to make a class constructor from arithmetical-type array with const size?
我有 class Q
并且想从大小为 3 的算术类型数组创建一个构造函数。我尝试使用模板 std::enable_if
和 std::is_arithmetic
并得到以下代码:
class Q {
public:
template <typename T>
Q (typename std::enable_if<std::is_arithmetic<T>::value, T>::type (&v)[3]) {
first = v[0];
second = v[1];
third = v[2];
}
private:
double first, second, third;
}
但是这段代码:
int arr[3] = { 1, 2, 3 };
Q q(arr);
无法编译,因为没有用于此类参数的构造函数:int[3]。这个问题有解决办法吗?
我会说你的 class Q
应该是其 first
... 成员类型的模板。
让我们假设出于某些原因这是不可取的,并且您确实希望通过例如first
...足够大的类型,例如int64_t
(注意 signed/unsigned 不匹配的可能问题)。在这种情况下,您可以依靠编译器来检查赋值:
struct Q {
template <typename T>
Q (T v[4]) {
first = v[0];
// ...
}
int64_t first;
// ...
};
int main()
{
int arithmetic[] = {0, 1, 2, 3};
int* not_arithmetic[4] = {};
Q q_a{arithmetic};
// Q q_na{not_arithmetic}; // error: assigning to 'int64_t' from incompatible type 'int *'
}
错误信息很清楚。
你的意思如下?
#include <string>
#include <type_traits>
struct Q
{
template <typename T,
typename = typename std::enable_if<
std::is_arithmetic<T>::value>::type>
Q (T const (&v)[3])
{ /* do someting */ }
};
int main()
{
int arr[3] {1, 2, 3};
Q a {arr}; // compile
Q b {{1, 2, 3}}; //compile
//Q c {{std::string{"1"}, std::string{"2"}, std::string{"3"}}}; // compilation error
}
您的原始代码的问题在于
template <typename T>
Q (typename std::enable_if<std::is_arithmetic<T>::value, T>::type (&v)[3])
编译器无法推导出类型 T
(如果我没记错的话是因为 v
的类型是 type
之后的类型 ::
那不是可推导的上下文)。
所以你必须允许 T
类型推导(我建议添加 const
这样构造函数也可以接受右值所以也可以接受 Q b {{1, 2, 3}};
)
template <typename T>
Q (T const (&v)[3])
而且,如果你想要 SFINAE enable/disable 构造函数,你可以像我前面的例子一样处理一个额外的模板参数。
申报后
int arr[4] = { 1, 2, 3, 4 };
Q q(arr);
你有类型 int[4] v&[4] 但你只需要 int。
为此,您可以将整个 class 声明为模板。
template <typename T> class Q {
public:
Q (typename std::enable_if<std::is_arithmetic<T>::value, T>::type (&v)[4]) {
first = v[0];
second = v[1];
third = v[2];
fouth = v[3];
}
};
并将其用作
int arr[4] = { 1, 2, 3, 4 };
Q<int> q(arr);
我有 class Q
并且想从大小为 3 的算术类型数组创建一个构造函数。我尝试使用模板 std::enable_if
和 std::is_arithmetic
并得到以下代码:
class Q {
public:
template <typename T>
Q (typename std::enable_if<std::is_arithmetic<T>::value, T>::type (&v)[3]) {
first = v[0];
second = v[1];
third = v[2];
}
private:
double first, second, third;
}
但是这段代码:
int arr[3] = { 1, 2, 3 };
Q q(arr);
无法编译,因为没有用于此类参数的构造函数:int[3]。这个问题有解决办法吗?
我会说你的 class Q
应该是其 first
... 成员类型的模板。
让我们假设出于某些原因这是不可取的,并且您确实希望通过例如first
...足够大的类型,例如int64_t
(注意 signed/unsigned 不匹配的可能问题)。在这种情况下,您可以依靠编译器来检查赋值:
struct Q {
template <typename T>
Q (T v[4]) {
first = v[0];
// ...
}
int64_t first;
// ...
};
int main()
{
int arithmetic[] = {0, 1, 2, 3};
int* not_arithmetic[4] = {};
Q q_a{arithmetic};
// Q q_na{not_arithmetic}; // error: assigning to 'int64_t' from incompatible type 'int *'
}
错误信息很清楚。
你的意思如下?
#include <string>
#include <type_traits>
struct Q
{
template <typename T,
typename = typename std::enable_if<
std::is_arithmetic<T>::value>::type>
Q (T const (&v)[3])
{ /* do someting */ }
};
int main()
{
int arr[3] {1, 2, 3};
Q a {arr}; // compile
Q b {{1, 2, 3}}; //compile
//Q c {{std::string{"1"}, std::string{"2"}, std::string{"3"}}}; // compilation error
}
您的原始代码的问题在于
template <typename T>
Q (typename std::enable_if<std::is_arithmetic<T>::value, T>::type (&v)[3])
编译器无法推导出类型 T
(如果我没记错的话是因为 v
的类型是 type
之后的类型 ::
那不是可推导的上下文)。
所以你必须允许 T
类型推导(我建议添加 const
这样构造函数也可以接受右值所以也可以接受 Q b {{1, 2, 3}};
)
template <typename T>
Q (T const (&v)[3])
而且,如果你想要 SFINAE enable/disable 构造函数,你可以像我前面的例子一样处理一个额外的模板参数。
申报后
int arr[4] = { 1, 2, 3, 4 };
Q q(arr);
你有类型 int[4] v&[4] 但你只需要 int。 为此,您可以将整个 class 声明为模板。
template <typename T> class Q {
public:
Q (typename std::enable_if<std::is_arithmetic<T>::value, T>::type (&v)[4]) {
first = v[0];
second = v[1];
third = v[2];
fouth = v[3];
}
};
并将其用作
int arr[4] = { 1, 2, 3, 4 };
Q<int> q(arr);