C++ - 如何从具有 const 大小的算术类型数组创建 class 构造函数?

C++ - How to make a class constructor from arithmetical-type array with const size?

我有 class Q 并且想从大小为 3 的算术类型数组创建一个构造函数。我尝试使用模板 std::enable_ifstd::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);