C++:如何从 make_shared 部分推导出模板参数 [英] C++: How to partially deduce template arguments from make_shared

查看:34
本文介绍了C++:如何从 make_shared 部分推导出模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了规避对部分提供的显式模板参数的限制,我嵌入了我想从中推导出类模板参数 (Internal) 到第二个结构 (Container) 的结构.

In order to circumvent the restriction on partially supplied explicit template arguments, I embed the struct from which I want to deduce the class template parameters (Internal) into a second struct (Container).

我想让代码的用户能够创建例如结果类型的共享指针.通过在结构中编写我自己的 create 函数,这工作得很好.

I would like to enable the user of the code to create e.g. shared pointers of the resulting type. By writing my own create function within the struct, this works just fine.

#include <memory>

/// Container that is used in order to partially specify template arguments
template <int A> struct Container {

  /// Contained type, of which the template arguments are deduced.
  template <int B> struct Internal {
    explicit Internal(std::integral_constant<int, B> fu) { (void)fu; }
  };

  /// Helper function
  template <int C>
  [[nodiscard]] static auto create(std::integral_constant<int, C> t) noexcept {
    return std::make_shared<Container<A>::Internal<C>>(t);
  }
};


int main() {
  Container<1>::Internal works{std::integral_constant<int, 8>{}};
  auto const worksAswell = Container<1>::create(std::integral_constant<int, 8>{});
}

但是当我尝试直接使用 make_shared 时,它失败了.我想让用户使用例如std::make_shared 函数.

But when I try to use make_shared directly, it fails. I would like to enable the user to use e.g. the std::make_shared function.

int main() {
  auto const fails = std::make_shared<Container<1>::Internal>(std::integral_constant<int, 8>{}); 
}

据我所知,这失败了,因为我无法部分指定模板参数,如果我不想指定所有模板参数,我也无法从 make_shared 函数中推导出它们.

From what I understand, this fails because I cannot partially specify template arguments, and I am unable to deduce them from the make_shared function if I don't want to specify all template parameters.


main.cc: In function ‘int main()’:
main.cc:21:74: error: no matching function for call to ‘make_shared<1>(std::integral_constant<int, 8>)’
   21 |   auto const fails = std::make_shared<1>(std::integral_constant<int, 8>{});
      |                                                                          ^
In file included from /usr/include/c++/9.2.0/memory:81,
                 from /home/juli/main9.cc:1:
/usr/include/c++/9.2.0/bits/shared_ptr.h:714:5: note: candidate: ‘template<class _Tp, class ... _Args> std::shared_ptr<_Tp> std::make_shared(_Args&& ...)’
  714 |     make_shared(_Args&&... __args)
      |     ^~~~~~~~~~~
/usr/include/c++/9.2.0/bits/shared_ptr.h:714:5: note:   template argument deduction/substitution failed:

是否可以启用像 std::make_shared 这样的生成器函数来部分推导这样的模板参数?可以在此处找到完整代码.

Is it possible to enable generator functions like std::make_shared to partially deduce template arguments like that? The entire code can be found here.

推荐答案

如果您创建自己的 make_shared 接受模板模板参数,我们可以使用 decltype 来推断结果类型并将其传递给 std::make_shared.

If you create your own make_shared that accepts a template template parameter we can use decltype to deduce the resulting type and pass that on to std::make_shared.

#include <memory>
#include <type_traits>

/// Container that is used in order to partially specify template arguments
template <int A> struct Container {

  /// Contained type, of which the template arguments are deduced.
  template <int B> struct Internal {
    explicit Internal(std::integral_constant<int, B> fu) { (void)fu; }
  };
};

template <template <int> typename partial, typename... Args>
auto make_shared(Args&&... args) {
    using target_type = std::remove_pointer_t<decltype(new partial{std::declval<Args>()...})>;
    return std::make_shared<target_type>(std::forward<Args>(args)...);
}

using std::make_shared;

int main() {
  auto const fails = make_shared<Container<1>::Internal>(std::integral_constant<int, 8>{});
  static_assert(std::is_same_v<const std::shared_ptr<Container<1>::Internal<8>>, decltype(fails)>);
}

这里唯一的问题是我们的 make_shared 需要知道预期目标的模板签名.

The only issue here is that our make_shared needs to know the template signature of the expected target.

从积极的方面来说,我们可以为不同的模板签名添加多个重载,并且我们可以使用一个参数包.

On the positive side we can add several overloads for different template signatures and we can use one parameter pack.

这篇关于C++:如何从 make_shared 部分推导出模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆