将新的构造函数添加到专用模板类

发布于 2025-02-13 22:30:25 字数 1201 浏览 3 评论 0原文

我有一个类别定义固定长度n的类。

template<int n>
struct array_container{
    /* some code here */
   int array[n];
};

假设我想将一个构造函数添加到array_container&lt; 3&gt;,符合以下方面的内容:

array_container<3>::array_container(int a0, int a1 ,int a2){
     array[0] = a0; 
     array[1] = a1; 
     array[2] = a1; 
}

我知道有两种方法:

一个是复制通用类的整个代码,替换<<<<<代码> n 带3,并添加我的构造函数:

template<>
struct array_container<3>{
   /* some code here */
   int array[3];
   
  array_container(int a0, int a1 ,int a2){
     array[0] = a0; 
     array[1] = a1; 
     array[2] = a1; }
};
 

这可以正确起作用,但缺点,需要从通用基础复制所有代码和方法。

另一种方法是在通用类中添加构造函数array_container(int a0,int a1,int a2); ,然后定义:

template<>
array_container<3>::  array_container(int a0, int a1 ,int a2){
     array[0] = a0; 
     array[1] = a1; 
     array[2] = a1; }

这具有与最佳不确定或在最佳dy处填充我的通用基础类别的缺点最坏的不正确的构造函数,例如 array_container&lt; 2&gt;(int a0,int a1,int a2)(取决于我是否将定义添加到通用基础中)。

是否有任何方法可以避免这两个陷阱? IE。不需要复制整个通用基本代码以进行专业化,也不需要在通用基础上添加不必要的构造函数?

I have a class defining an array of fixed length n, with some methods.

template<int n>
struct array_container{
    /* some code here */
   int array[n];
};

Let's say I want to add a constructor to array_container<3>, something along the lines of:

array_container<3>::array_container(int a0, int a1 ,int a2){
     array[0] = a0; 
     array[1] = a1; 
     array[2] = a1; 
}

I know of two ways to do this:

One is to copy the entire code of the generic class, replacing n with 3, and add my constructor:

template<>
struct array_container<3>{
   /* some code here */
   int array[3];
   
  array_container(int a0, int a1 ,int a2){
     array[0] = a0; 
     array[1] = a1; 
     array[2] = a1; }
};
 

This works correctly, but has the disadvantage of needing to copy all the code and methods from the generic base.

Another method is to add a constructor array_container(int a0, int a1, int a2); in the generic class, then define:

template<>
array_container<3>::  array_container(int a0, int a1 ,int a2){
     array[0] = a0; 
     array[1] = a1; 
     array[2] = a1; }

This has the disadvantage of populating my generic base class with at best undefined or at worst incorrect constructors, such as
array_container<2>(int a0, int a1 ,int a2) (undefined or incorrect depending on whether or not I add the definition to the generic base or not).

Is there any approach that avoids both pitfalls? Ie. doesn't need to copy-paste the entire generic base code for the specialization, and doesn't add unnecessary constructors to the generic base?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

南街女流氓 2025-02-20 22:30:25

为什么不简单地使用

template <std::size_t size>
struct MyArrayWithFunctions : std::array<int, size> {
    /* some functions */
};

std :: array允许汇总初始化,甚至可以推论大小,以便您可以简单地编写

MyArrayWithFunctions arr{1,2,3};

您可以为自己的类添加扣除指南,但是为什么重新实现array

Why not simply use

template <std::size_t size>
struct MyArrayWithFunctions : std::array<int, size> {
    /* some functions */
};

std::array allows aggregate initialization and even deduces the size so you can simply write

MyArrayWithFunctions arr{1,2,3};

You can add a deduction guideline for your own class but why re-implement array?

安稳善良 2025-02-20 22:30:25

是否有任何避免这两个陷阱的方法? IE。不需要复制整个通用基本代码以进行专业化,也不需要在通用基础上添加不必要的构造函数?

忽略@goswin von von Brederlow提到的事实,您似乎正在重新发明轮子(std :: array and code>和汇总初始化),C ++ 20的需要表达允许您在一个中定义构造函数仅限于某些专业的主要模板。例如:

#include <type_traits>

// Helper trait for constraining a ctor to a set
// of specializations.
template <int n, int... ns> struct is_one_of {
  static constexpr bool value{false};
};

template <int n, int n0, int... ns> struct is_one_of<n, n0, ns...> {
  static constexpr bool value{(n == n0) || is_one_of<n, ns...>::value};
};

template <int n, int... ns>
inline constexpr bool is_one_of_v{is_one_of<n, ns...>::value};

template <int n> struct array_container {
  /* some code here */
  int array[n];

  // Constrained to n == 3 or n == 5.
  template <typename... Args>
      requires(std::is_same_v<Args, int> &&...) && (sizeof...(Args) == n) &&
      is_one_of_v<n, 3, 5 /*, ... */> array_container(Args... args)
      : array{args...} {}
};

// Demo.
array_container<3> arr3{1, 2, 3};       // OK
array_container<4> arr4{1, 2, 3, 4};    // Error (no matching ctor)
array_container<5> arr5{1, 2, 3, 4, 5}; // OK

Is there any approach that avoids both pitfalls? Ie. doesn't need to copy-paste the entire generic base code for the specialization, and doesn't add unnecessary constructors to the generic base?

Ignoring the fact that, as @Goswin von Brederlow mentions, you seem to be reinventing the wheel (std::array and aggregate initialization), C++20's requires-expressions allows you to define constructors in a primary template that are constrained to only certain specializations. E.g.:

#include <type_traits>

// Helper trait for constraining a ctor to a set
// of specializations.
template <int n, int... ns> struct is_one_of {
  static constexpr bool value{false};
};

template <int n, int n0, int... ns> struct is_one_of<n, n0, ns...> {
  static constexpr bool value{(n == n0) || is_one_of<n, ns...>::value};
};

template <int n, int... ns>
inline constexpr bool is_one_of_v{is_one_of<n, ns...>::value};

template <int n> struct array_container {
  /* some code here */
  int array[n];

  // Constrained to n == 3 or n == 5.
  template <typename... Args>
      requires(std::is_same_v<Args, int> &&...) && (sizeof...(Args) == n) &&
      is_one_of_v<n, 3, 5 /*, ... */> array_container(Args... args)
      : array{args...} {}
};

// Demo.
array_container<3> arr3{1, 2, 3};       // OK
array_container<4> arr4{1, 2, 3, 4};    // Error (no matching ctor)
array_container<5> arr5{1, 2, 3, 4, 5}; // OK
夏末的微笑 2025-02-20 22:30:25

更容易的解决方案是用阵列构造它(原始)。

template<int n>
struct array_container{
    int array[n];
    
    array_container(std::array<int, n> arrayIn)
    {
        std::copy(arrayIn.begin(), arrayIn.end(), array); 
    }
};

否则,您可能会弄乱variadic模板和参数解开包装。

The easier solution would be to construct it with an array(in place).

template<int n>
struct array_container{
    int array[n];
    
    array_container(std::array<int, n> arrayIn)
    {
        std::copy(arrayIn.begin(), arrayIn.end(), array); 
    }
};

Otherwise you can mess with variadic templates and parameter unpacking.

再可℃爱ぅ一点好了 2025-02-20 22:30:25

如果碰巧具有C ++ 17编译器,则可以使用以下代码:

#include <type_traits>

// class definition
template<int n>
struct array_container {
    int array[n];

    template<typename... Args, typename std::enable_if_t<(std::is_same_v<int, Args> && ...) && (sizeof...(Args) == n), bool> = true>
    array_container(Args... args):
        array{args...}
    {}
};

// user defined template deduction guide
template<typename... Args>
array_container(Args...) -> array_container<sizeof...(Args)>;

并使用它像

array_container<3> x {1,2,3};

等参数数量推导的大小。

// n deduced to 3 from the number of arguments
array_container x {1,2,3};

构造函数一样从构建器(例如a

看到它活在 Godbolt

If happen to have a C++17 compiler you can use the following code:

#include <type_traits>

// class definition
template<int n>
struct array_container {
    int array[n];

    template<typename... Args, typename std::enable_if_t<(std::is_same_v<int, Args> && ...) && (sizeof...(Args) == n), bool> = true>
    array_container(Args... args):
        array{args...}
    {}
};

// user defined template deduction guide
template<typename... Args>
array_container(Args...) -> array_container<sizeof...(Args)>;

and use it like

array_container<3> x {1,2,3};

or even let the size be deduced from the number of arguments like

// n deduced to 3 from the number of arguments
array_container x {1,2,3};

The constructor is a variadic template, taking any number of int arguments (the latter is enforced by the std::enable_if_t template parameter) and initializes the array member from them. A user defined deduction guide can be used to automatically deduce the n parameter from the number of arguments, that you pass to the constructor.

See it live on godbolt.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文