C++等效于C#9.0 New()与推论类型

发布于 2025-01-23 17:37:29 字数 770 浏览 0 评论 0原文

C#9+知道从LHS推断RHS的类型,只需使用正确的参数调用new并具有您的对象。无需重复冗长的类型,类型总是正确的,

List<int> ints = New(capacity: 10_000);

可以在C ++中完成相同的干吗?

我使用“安全”的新和删除有类似的东西,这些新和删除将目标作为参数和使用模板推断出类型等,但是它比my_var = new(arg1,arg1,arg2,arg2)>

请注意,这是一个有关如何做a = new(1,2,3)(例如C#)的问题; vector&lt; toupel&lt; int,float,car&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&lt; vector&lt; vector&lt; toupel&lt; int,float,float,char&gt;&gt;&gt;&gt;&gt;&gt;》 '有时用shared_ptr和CO包装。

new-operator

C# 9+ knows to deduce the type of RHS from LHS, just call New with the correct parameters and have your object. No need to repeat lengthy types, and the type is always correct

List<int> ints = New(capacity: 10_000);

Can the same DRY new be done in c++ ?

I have something similar using "safe" new and delete that take the target as argument and deduce type etc using templates, but it is a bit less readable than just my_var = new(arg1, arg2, arg3)

Please note this is a question about how to do a = new(1,2,3) , like C#, and not about now to create new objects in c++ which make look something like list<vector<toupel<int,float,char>>>*a = new list<vector<toupel<int,float,char>>>()
' sometimes wrapper with shared_ptr and co.

new-operator

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

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

发布评论

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

评论(4

乖不如嘢 2025-01-30 17:37:29

首先,您应该很少在现代C ++中使用明确的内存管理。使用智能指针,例如 std :: simelor_ptr带有所有权语义。

至于您的问题,您可以以大致相同的方式执行此操作,但可以相反:声明中的类型自动划分,并指定new表达式中的类型:

auto* my_pointer = new MyClass<template_type>(arguments, to, constructor);

或使用唯一指针:

auto my_unique_pointer = std::make_unique<MyClass<template_type>>(arguments, to, constructor);

至于容器的主题,您几乎绝不应该向容器施加指针。如果需要容器,只需创建一个实例:

std::vector<int> v1(10000);  // Create a vector of 10000 integers

First of all you should seldom use explicit memory management in modern C++. Use smart pointers like std::unique_ptr with ownership semantics.

As for your problem, you can do it in roughly the same way, but kind of opposite instead: Auto-deduction of the type in the declaration, and specify the type in the new expression:

auto* my_pointer = new MyClass<template_type>(arguments, to, constructor);

Or using unique pointers:

auto my_unique_pointer = std::make_unique<MyClass<template_type>>(arguments, to, constructor);

As for the subject of containers, you should almost never make pointers to containers. If you need a container, just create an instance of it:

std::vector<int> v1(10000);  // Create a vector of 10000 integers
凉城 2025-01-30 17:37:29

这是您可以在C ++中的新(警告,测试)

  template <typename ... Args>
  struct NewHelper : public std::tuple<Args...>
  {
      using std::tuple<Args...>::tuple;

      template <typename R>
      operator R*()
      {
          return new_impl<R>(std::make_index_sequence<sizeof ... (Args)>{});
      }

      template <typename R, std::size_t... I>
      R* new_impl(std::index_sequence<I...>)
      {
          return new R(std::get<I>(static_cast<std::tuple<Args...>&>(*this))...);
      }
  };

  template <typename ... Args>
  auto New(Args&&... args)
  {
      return NewHelper<Args&&...>(std::forward<Args>(args)...);
  }

用法:

int* x;
x = New(42);

std::tuple<int&, std::string>* y;
y = New(*x, "Hello dangling reference");

请注意,我说您可以写它,而不是您应该写它。这是高度违反直觉的抗异错C ++,绝对不应让生产代码接近。尝试危险事物很有趣,但是有趣的是有趣,而且工作是工作。

Here's how you could write New in C++ (warning, lightly tested)

  template <typename ... Args>
  struct NewHelper : public std::tuple<Args...>
  {
      using std::tuple<Args...>::tuple;

      template <typename R>
      operator R*()
      {
          return new_impl<R>(std::make_index_sequence<sizeof ... (Args)>{});
      }

      template <typename R, std::size_t... I>
      R* new_impl(std::index_sequence<I...>)
      {
          return new R(std::get<I>(static_cast<std::tuple<Args...>&>(*this))...);
      }
  };

  template <typename ... Args>
  auto New(Args&&... args)
  {
      return NewHelper<Args&&...>(std::forward<Args>(args)...);
  }

Usage:

int* x;
x = New(42);

std::tuple<int&, std::string>* y;
y = New(*x, "Hello dangling reference");

Note, I said that you could write it, not that you should write it. This is highly counter-intuitive, anti-idiomatic C++ that should never be let near production code. It's fun to experiment with dangerous things, but fun is fun and work is work.

老娘不死你永远是小三 2025-01-30 17:37:29

这是我的safe_newsafe_delete variant:
哪个有效,但不像我喜欢的

template<typename T>
void safe_delete(T **p) {
    if (*p == nullptr)
        return; // do not delete twice
    delete *p;
    *p = nullptr;
}

// call new but make sure to delete previous object
template<typename T, typename... Types>
void safe_new(T **p, Types... args) {
    if (*p != nullptr)
        delete p; // do not delete twice
    *p = new std::remove_pointer<std::remove_pointer<decltype(p)>::type>::type(args...);
}

审美方式:

PagedHashMap<tuple<int, int, float>, Edge, boost::hash<tuple<int, int, float>> > *edge_map;

带有参数的新来,但没有明确的类型:

safe_new(&edge_map, 2000000));

请注意,这不是一个确切的答案 - 更好的答案将是:

edge_map = new(20000);

Here is my safe_new and safe_delete variant:
Which works but is not as aesthetes as I like

template<typename T>
void safe_delete(T **p) {
    if (*p == nullptr)
        return; // do not delete twice
    delete *p;
    *p = nullptr;
}

// call new but make sure to delete previous object
template<typename T, typename... Types>
void safe_new(T **p, Types... args) {
    if (*p != nullptr)
        delete p; // do not delete twice
    *p = new std::remove_pointer<std::remove_pointer<decltype(p)>::type>::type(args...);
}

Usage:

PagedHashMap<tuple<int, int, float>, Edge, boost::hash<tuple<int, int, float>> > *edge_map;

Call new with parameters but without explicit type:

safe_new(&edge_map, 2000000));

Please note this is not an exact answer - A better answer would be something like:

edge_map = new(20000);
自我难过 2025-01-30 17:37:29

首先,C ++和C#Sharp中的含义不同。使用C#,每当您尝试调用构造函数时,都需要使用new。但是,对于C ++,您只应使用new在尝试创建一个生命周期的对象时不受其创建的范围的限制。即使您确实需要手动管理对象寿命,您应该考虑使用智能指针。

因此,C#中的该代码:

List<int> ints = new(capacity: 100);
ints = new(capacity: 1000);

要在C ++中重写,您确实不应使用new。相反,它应该像:

list<int> ints(100);
ints = list<int>(1000);

现在回到您的问题一样,您想知道第二行,是否可以重新分配ints而无需输入其类型。虽然此示例中的类型很短,但如果类型实际上很长,可能会很详尽。

您可以使其短的一种方法是创建一个可以创建任何对象的助手函数:

template<typename ReturnType, typename ... Args>
ReturnType create(Args&& ... args)
{
    return ReturnType(std::forward<Args>(args)...);
}

它的作用就是将所有参数转发到return typepe的构造函数。然后,您可以像以下内容一样使用它:

SOME_REALLY_REALLY_LONG_TYPE_NAME foo(100);
foo = create<decltype(foo)>(1000);

但是,exltype(foo)仍然感觉冗长且多余。要进一步缩短它,您可以创建另一个功能,以foo作为参考,然后在该函数中执行创建

template<typename Original, typename ... Args>
void reassign(Original& original, Args&& ... args)
{
    original = create<Original>(std::forward<Args>(args)...);
}

现在您的代码将变为:

SOME_REALLY_REALLY_LONG_TYPE_NAME foo(100);
reassign(foo, 1000);

First, the meanings of new in C++ and C# sharp are different. With C#, you would need to use new whenever you try to invoke a constructor. However with C++, you should only ever use new when you are trying to create an object whose lifetime is not limited by the scope it was created in. And even if you do need to manage object lifetime manually, you should consider using smart pointer instead.

So this code in C#:

List<int> ints = new(capacity: 100);
ints = new(capacity: 1000);

To rewrite it in C++, you really should not use new. Instead it should be written like:

list<int> ints(100);
ints = list<int>(1000);

Now back to your problem, you were wondering at the second line, if you can reassign ints without typing out its type. While the type in this example is quite short, it could be quite verbose if the type was actually pretty long.

One way you can make it shorter is by creating a helper function that can create any object:

template<typename ReturnType, typename ... Args>
ReturnType create(Args&& ... args)
{
    return ReturnType(std::forward<Args>(args)...);
}

What it does is simply forward all the arguments to the ReturnType's constructor. You can then use it like:

SOME_REALLY_REALLY_LONG_TYPE_NAME foo(100);
foo = create<decltype(foo)>(1000);

However, the decltype(foo) still feels verbose and redundant. To further shorten it, you can create another function that takes in foo as a reference, then do the create inside that function:

template<typename Original, typename ... Args>
void reassign(Original& original, Args&& ... args)
{
    original = create<Original>(std::forward<Args>(args)...);
}

Now your code would become:

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