如何防止函数模板参数推导

How to prevent function template argument deduction

提问人:francisC 提问时间:10/15/2023 最后编辑:francisC 更新时间:10/15/2023 访问量:139

问:

这是一个玩具的例子,但它说明了我猜的观点...... 我需要确保仅当指定参数类型时才调用模板化函数(可以是类成员),因为对于几种选择的类型,专用化将有所不同。

template<typename T>
void ff(T x) { cout << "NO WAY!!! : " << x << endl; }

template<>
void ff(uint16_t x) { cout << "uint16_t thing: " << x << endl; }

template<>
void ff(uint32_t x) { cout << "uint32_t thing: " << x << endl; }

// ----------------------------------------------------------

编译并运行该示例,它会产生:

ff<uint16_t>(10); // -> uint16_t thing: 10

ff(10); // -> NO WAY!!! : 10 ... This is the case I'm trying to avoid ...

为了禁止编译第二个函数调用,我已将第一个声明替换为:

template<typename T>
void ff(std::type_identity_t<T> && x) { cout << "NO NO NO! : " << x << endl; }

但它无法编译......

error: template-id ‘ff<>’ for ‘void ff(uint16_t)’ does not match any template declaration

(GCC 12.3.0)

怎么做呢?

谢谢!

C++ C++20 模板参数推导

评论

6赞 Tim Roberts 10/15/2023
那为什么要使用模板呢?为什么不命名你的函数和?模板的重点在于编译器根据提供的类型选择适当的函数。如果你不想要它,就不要使用它。ff_uint16ff_uint32
2赞 Yksisarvinen 10/15/2023
专门化模板函数非常困难,以至于 C++ 标准甚至有一个俳句。我不建议这样做。如果我没记错的话,你只需要?这将禁止使用 和 以外的参数进行调用,无需使用模板(好吧,不是显式的)。void ff(auto&& x) = delete;fuint16_tuint32_t
4赞 user17732522 10/15/2023
如果是,应该编译吗?也就是说,你真的想强制使用显式模板参数还是只避免隐式转换?ff(10u);uint32_tunsigned int
2赞 user17732522 10/15/2023
无论如何,错误是不属于那里的。(您也不会在其他模板和专业化中使用按引用传递。然后,您还需要在显式专业化中明确指定模板参数,例如 而不是。&&ff<uint16_t>(uint16_t x)ff(uint16_t x)
0赞 francisC 10/15/2023
是的,&&是虚假的;-)但是您的所有评论都包含问题的答案!我会把它放在帖子的正文中......

答:

4赞 francisC 10/15/2023 #1

怎么做...

PS:您的评论让我走上了正确的轨道!

当然,没有必要在简单的函数上使用模板,但是如果我们有一个带有模板成员函数的类,它会很方便;-)

唯一缺少的是专业化的模板 arg 类型......ff<T>()

#include <type_traits>

template<typename T>
void ff(std::type_identity_t<T> x) { /* force arg type */ }

template<>
void ff<uint16_t>(uint16_t x) { cout << "uint16_t thing: " << x << endl; }

template<>
void ff<uint32_t>(uint32_t x) { cout << "uint32_t thing: " << x << endl; }

现在,让我们编译:

ff(10)                       // no template arg type -> ERROR
ff<uint16_t>(10);            // Ok! it compiles :-)

是的,如果缺少模板类型,我想编译器给出错误,迫使我指定它,它现在做了一些事情。

谢谢大家,你们一直很有帮助!

cppreference.com 处的 type_traits 的简短链接如下:

https://en.cppreference.com/w/cpp/types/type_identity