【发布时间】:2025-12-13 04:35:01
【问题描述】:
我有一个看起来像这样的模板类/结构:
template <typename T, typename U>
struct S
{
unsigned int operator()(T t, U u) const;
};
我想确保专业化尊重这个接口。
不幸的是,我可以用不同的返回类型专门化这个结构。例如,如果我部分专门返回 bool 而不是 unsigned int,我希望得到一个编译器错误,但编译器似乎并不关心:
template <typename T>
struct S<T,nullptr_t>
{
bool operator()(T t, nullptr_t u) const { return 2; }
};
Example@ideone.com
在上面的例子中,专用版本应该返回2,但是由于返回类型是bool,所以返回值被转换为true,然后显示为1。
为什么编译器会接受这个?
如何防止程序员使用错误的返回类型(甚至错误的参数)专门化模板?
我知道我可以使用基本模板类/结构中的虚拟方法来实现我想要的,并在子级中使用 override 关键字:
Solution with override(不编译,这很好)
但是拥有一个虚拟方法肯定会创建一个虚拟表,我想尽可能避免这种情况,特别是因为我在运行时不需要虚拟表。除非有一个技巧可以在不构建虚拟表的情况下做同样的事情?
另外,我知道如果我可以部分专业化方法或者我可以依赖非部分专业化,问题会更简单,但前者在 C++ AFAIK 中是不可能的,而后者不包括我需要的情况在我的程序中。
【问题讨论】:
-
“我怎样才能防止程序员使用错误的返回类型专门化模板”你不能。程序员可以编写与您的原始模板完全不同的特化,并随心所欲地使用它们。你唯一能做的就是确保你编写的函数只接受“好的”特化。
-
我想你可以看看en.cppreference.com/w/cpp/types/result_of,如果推断的类型是你想要的,做一些静态断言。如果错误,静态断言将停止编译并出现错误。
-
@wdudzik 我想过检查结果类型(使用
decltype或std::result_of),但这意味着要么每个调用者都需要检查它,要么每个专业化都需要检查它,这有点重。也许我可以使用 C++20 的概念自动检查,但我的编译器与 C++20 不兼容。 -
你为什么在乎?当然,人们可以写出疯狂的东西,但他们甚至可以不专门写一些不明智的东西。
-
@PasserBy 我确实关心与引入
override关键字相同的原因:确保在编写代码时尊重接口,并且在以后更新时也尊重接口开。
标签: c++ templates overriding partial-specialization