C++:如何从 make_shared 部分推导模板参数

标签 c++ templates arguments c++17 make-shared

为了规避restriction on partially supplied explicit template arguments ,我将要从中推导出类模板参数 (Internal) 的结构嵌​​入到第二个结构 (Container) 中。

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

#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 函数。

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

据我了解,这会失败,因为我无法部分指定模板参数,并且如果我不想指定所有模板参数,则无法从 make_shared 函数中推断出它们。


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 这样的生成器函数来部分推导这样的模板参数?完整代码可以找到here .

最佳答案

如果您创建自己的 make_shared 并接受模板模板参数,我们可以使用 decltype 来推断结果类型并将其传递给 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 需要知道预期目标的模板签名。

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

关于C++:如何从 make_shared 部分推导模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59886167/

相关文章:

django tiny mce 是普通文本字段而不是富文本格式?请修复。包括设置

C++,实例化一个通用节点,使用模板存储一个对象的实例

python - 关于 python mysqldb TypeError

c++ - 在 Ubuntu 上缺少与 MinGW 的 header 依赖关系

c++ - 矩阵乘法

c++ - 类方法中 For Loop 的运行时错误 - 数据结构

arguments - 如何将参数传递给 TCL 源

c++ - 函数参数中 int * array 和 int array[] 的区别

c++ - 带有默认模板参数的友元函数模板

linux - Bash shell 提示我没有使用的无效选项...仅适用于 *.mp4 文件扩展名