是否可以显式实例化返回未指定类型的模板化函数?

Is it possible to explicitly instantiate a templated function that returns an unspecified type?

提问人:MarkB 提问时间:12/16/2022 最后编辑:MarkB 更新时间:12/16/2022 访问量:105

问:

我正在尝试对模板化函数执行显式实例化,以提高代码覆盖率结果的准确性。当返回类型已知时,我知道如何做到这一点。我可以通过定义返回 .如果没有这个额外的函数定义,是否有可能实现结果?void

#include <concepts>

template <typename T>
struct Gen {
    T operator()() const { return T{}; }
};
template <std::default_initializable T>
Gen<T> buildKnown() {
    return Gen<T>{};
}
template <std::default_initializable T>
std::invocable auto buildConstrained() {
    return Gen<T>{};
}
template <std::default_initializable T>
std::invocable auto buildInternal() /* -> decltype(??) */ {
    struct Local : Gen<T> {};
    return Local{};
}

// Perform explicit instantiation of each templated function.
template Gen<int> buildKnown<int>();        // works
template Gen<int> buildConstrained<int>();  // somewhat surprised this doesn't work.
template auto buildInternal<int>();         // not surprised this doesn't work

// Indirectly instantiate buildInternal through a wrapper function.
template <typename T> void buildInternalWrapper() { buildInternal<T>(); }
template void buildInternalWrapper<int>();

编辑:修复了类型约束(最初是)使问题更加混乱。std::invocable<int>

C++ C++20 显式实例化

评论

0赞 NathanOliver 12/16/2022
auto在这种情况下,基本上是一个隐式模板参数。您必须显式拼写出所需的每个返回类型,因此类型意味着实例化。NN
0赞 MarkB 12/16/2022
@NathanOliver,如果我理解你的意思,那么我会期待模板 Gen<int> buildConstrained<int>() 的显式实例化;编译。该行失败并出现编译错误。

答:

3赞 Brian Bi 12/16/2022 #1

好吧,首先,您推导的返回类型约束是错误的。例如,请考虑您编写的以下函数模板:

template <std::default_initializable T>
std::invocable<T> auto buildConstrained() {
    return Gen<T>{};
}

如果用 = 实例化会发生什么?它将成为Tint

std::invocable<int> auto buildConstrained() {
    return Gen<int>{};
}

占位符类型说明符表示需要推导类型,如果我们称之为推导类型,则必须满足约束。因此,只有在满足时,此函数定义才是正确的格式。但事实并非如此; 可使用 0 个参数调用,而不是使用 1 个参数调用。std::invocable<int> autoUstd::invocable<U, int>std::invocable<Gen<int>, int>Gen<int>int

我猜你的意思是:

template <std::default_initializable T>
std::invocable auto buildConstrained() {
    return Gen<T>{};
}

在进行了这样的修改之后,我们现在可以声明显式实例化:

template std::invocable auto buildConstrained<int>();

使用占位符类型说明符的函数模板的显式实例化也必须使用相同的占位符类型说明符,而不是推导的类型。

评论

0赞 MarkB 12/16/2022
是的。我在推导的返回类型约束上打错了字。感谢您对我的错误的回应。