请考虑以下示例(标签调度,可变参数模板,完美转发等等):
#include#include #include struct A { }; struct B { }; void doIt(A&&, const std::string &) { std::cout << "A-spec" << std::endl; } template void doIt(T&&, Args&&...) { std::cout << "template" << std::endl; } template void fn(Args&&... args) { doIt(T{}, std::forward (args)...); } int main() { const std::string foo = "foo"; std::string bar = "bar"; fn(foo); fn(bar); fn(foo); }
在这种情况下,输出是:
A-spec template template
原因很明显,它并没有打扰我.
我想要实现的是doIt
在两种情况下调用函数的第一个实例,无论字符串是否具有const说明符.
当然,一个可能的解决方案是doIt
使用正确的原型定义一个新的,无论如何我想知道是否还有另一个解决方案.
到目前为止,我已经试图通过它来获得它add_const
,但我很确定我错过了一些东西.
有没有可行的解决方案来静默添加const说明符并让它工作?
编辑
我已经更新了上面的例子,以便更加符合真正的问题.
此外,尽管有趣的答案,我忘了引用这只是一个简化的例子,所以真正的问题不仅仅涉及std::string
.相反,它可能发生(作为示例)标记A
参数是int
和const std::string &
,而对于标记B
,参数是float
,类的实例C
,等等.
因此,试图以某种方式解决问题的那些答案std::string
将无法解决真正的问题,对不起.
引入两个独立的函数,以便它们不会相互冲突,编译器不会引起任何歧义错误:
void doIt(A&&, const std::string &) { std::cout << "A-spec" << std::endl; } templatevoid doIt_template(T&&, Args&&...) { std::cout << "template" << std::endl; }
优先考虑两个额外的重载; 首选的是尝试调用目标函数的专用非模板化版本:
templateauto fn_impl(int, Args&&... args) -> decltype(doIt(T{}, std::forward (args)...), void()) { doIt(T{}, std::forward (args)...); } template void fn_impl(char, Args&&... args) { doIt_template(T{}, std::forward (args)...); }
介绍一个单一的通用调度员:
templatevoid fn(Args&&... args) { fn_impl (0, std::forward (args)...); }
DEMO