c++ - 在函数模板中,如何根据另一个参数确定一个参数的类型

标签 c++ templates c++17 function-templates

我想实现一个函数模板,它接受两个参数,一个 T* 和一个 T,但是第二个参数的类型由第一个参数决定。这是一个最小的非工作示例:

#include <cstddef>
#include <cstring>
#include <cstdint>
#include <type_traits>
#include <vector>

template<typename T> void
patch(T *dst, T src)
{
  static_assert(std::is_standard_layout_v<T>);
  std::byte *p = reinterpret_cast<std::byte *>(&src);
  std::vector newval(p, p + sizeof(src));

  // In the real code, memcpy happens later if a transaciton commits
  std::memcpy(dst, newval.data(), newval.size());
}

int
main()
{
  std::uint16_t u16;
  patch(&u16, 0);  // Fails to compile because 0 is int, not uint16_t
}

不幸的是,这段代码无法编译,因为无法在 patch(&u16, 0) 中推断出要修补的类型 T ,因为 0 是一个 int 而不是 std::uint16_t .显然我可以投 0 或调用 patch<uint16_t>(...) ,但在理想情况下我不必这样做。

另一方面,如果第二个参数涉及某种非平凡类型的计算,我可以解决这个问题。例如,如果我将函数声明为:

template<typename T> void
patch(T *dst, std::decay_t<T> src) {/*...*/}

当我最初问这个问题时,我实现了以下内容并认为它不起作用。但是,我一定是犯了一个错误,因为正如所选答案所指出的那样,它确实有效:

template<typename T> struct sametype {
  using type = T;
};
template<typename T> using sametype_t = typename sametype<T>::type;

template<typename T> void
patch(T *dst, sametype_t<T> src) {/*...*/}

我的问题是,可以应用于模板函数参数以强制其类型由同一函数的不同参数的类型推断出来的最小转换是什么?

最佳答案

这正是 std::type_identity_t<T> 旨在解决。此转换创建了所谓的非推导上下文,您已为类型为 T 的第二个参数请求了它.不幸的是,这种类型特征直到 C++20 标准才被引入。

您可以继续use the one you've implemented (顺便说一句,是的,它至少根据 godbolt 进行编译),或者如果您使用的是 boost,则有一个 boost::type_identity_t<T> 可用。

不过,为了直接回答您的问题,我相信 C++17 中所需的最最小 转换之一是 this :

template<typename T> void
patch(T *dst, std::enable_if_t<true, T> src)

关于c++ - 在函数模板中,如何根据另一个参数确定一个参数的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66945729/

相关文章:

c++ - istringstream 运算符>> 返回值

c++ - 如何使用模板链接数据结构中的节点对象?

c++ - 模板类错误 C++

c++ - 通过模板检查是否存在带有参数列表的类成员函数?

c++ - 如何将一个 std::vector move 附加到另一个?

c++ - 在C++中,如何根据运行时条件构造引用不同istream对象的对象?

c++ - dlsym() + RTLD_NEXT 在 Ubuntu 20.04 上无法正常工作

c++ - 将可变函数作为参数传递

c++ - 从类模板派生类

c++ - std::chrono::duration::max() 不适用于线程支持库