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

查看:74
本文介绍了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天全站免登陆