本文介绍了在函数模板中,如何确定一个基于另一个参数的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个带有两个参数(T *和T)的函数模板,但是第二个参数的类型由第一个确定.这是一个最小的无效示例:

I'd like to implement a function template that takes two arguments, a T* and a T, but where the second argument's type is determined by the first. Here's a minimal non-working example:

#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>(...),但在理想情况下,我不必这样做.

This code unfortunately fails to compile because the type T to patch cannot be inferred in patch(&u16, 0), because 0 is an int rather than a std::uint16_t. Obviously I could cast the 0 or call patch<uint16_t>(...), but in an ideal world I wouldn't have to.

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

On the other hand, I can work around the problem if the second argument involves some kind of non-trivial type computation. For example, the code will compile if I declare the function as:

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

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

When I originally asked the question, I implemented the following and believed it didn't work. I must have made a mistake, however, because as pointed out by the selected answer, it does in fact work:

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) {/*...*/}

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

My question is what's the minimal transformation one can apply to a template function argument to force its type to be inferred by the type of a different argument to the same function?

推荐答案

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

This is exactly the kind of scenario that std::type_identity_t<T> is intended to resolve. This transformation creates what's called a non-deduced context, which you've requested for your second parameter of type T. Unfortunately this type trait wasn't introduced until the C++20 standard.

您可以继续使用您已实现的实现(顺便说一句,是的确实至少根据Godbolt进行了编译),或者,如果您使用的是Boost,则存在 ="nofollow noreferrer"> boost :: type_identity_t< T> .

You can continue to use the one you've implemented (which by the way, yes it does compile at least according to godbolt), or if you're using boost, there is a boost::type_identity_t<T> available.

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

To answer your question directly though, I believe one of the most minimal transformations necessary in C++17 would be this:

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

这篇关于在函数模板中,如何确定一个基于另一个参数的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 08:11