C++ 强制先尝试一个过载,然后再尝试另一个过载
作为一个更广泛问题的示例,考虑到这两个重载,您可能会认为在传递数组时,数组版本将具有优先权:C++ 强制先尝试一个过载,然后再尝试另一个过载,c++,templates,sfinae,C++,Templates,Sfinae,作为一个更广泛问题的示例,考虑到这两个重载,您可能会认为在传递数组时,数组版本将具有优先权: template <size_t N> void bar(const char (&)[N]) { std::cout << "array, size=" << N-1 << std::endl; } void bar(const char *s) { std::cout << "raw, size=" <&
template <size_t N>
void bar(const char (&)[N]) {
std::cout << "array, size=" << N-1 << std::endl;
}
void bar(const char *s) {
std::cout << "raw, size=" << strlen(s) << std::endl;
}
在不作进一步修改的情况下,我们可以这样写:
template<typename ...Args>
auto try_bar1_then_bar2(Args&& ...args) -> ??? {
... will first attempt to perfect forward to bar1 ...
... only if bar1 cannot be called, fallback to bar2 ...
}
模板
自动尝试\u bar1\u然后\u bar2(Args&&…Args)->???{
…将首先尝试完美的前进到bar1。。。
…仅当无法调用bar1时,才回退到bar2。。。
}
我在这个问题中使用了一些C++ 11,并且有一个完美的转发,但是我猜一般的问题也适用于前面的C++。是否有一种简单、通用的方法来强制重载优先级的重新排序?当一组函数(名称不同?)可(几乎不可)调用时,如何准确控制它们的尝试顺序?某些表达式如下:
template<typename ...Args>
auto try_bar1_then_bar2_IMPL(int, Args&& ...args) -> decltype( bar1(forward<Args>(args)...) ) {
cout << "Yes, we can call bar1" << endl;
return bar1(forward<Args>(args)...);
}
template<typename ...Args>
auto try_bar1_then_bar2_IMPL(char, Args&& ...args) -> void {
cout << "No, can't call bar1, calling bar2 instead." << endl;
return bar2(forward<Args>(args)...);
}
template<typename ...Args>
auto try_bar1_then_bar2(Args&& ...args) -> decltype( try_bar1_then_bar2_IMPL(0, forward<Args>(args)...) ) {
return try_bar1_then_bar2_IMPL(0, forward<Args>(args)...);
}
可以使用模板包装参数,以获得所需的重载函数:
#include <cstring>
#include <iostream>
template <typename T>
struct Wrap
{
const T& value;
Wrap(const T& value)
: value(value)
{}
};
template <typename T>
inline Wrap<T> wrap(const T& value) {
return Wrap<T>(value);
}
template <size_t N>
void bar(const Wrap<char[N]>&) {
std::cout << "array, size=" << N-1 << std::endl;
}
void bar(const Wrap<const char *>& s) {
std::cout << "raw, size=" << strlen(s.value) << std::endl;
}
template <typename T>
void bar(const T& value) {
bar(wrap(value));
}
int main(int argc, char* argv[]) {
const char a[] ="hello";
const char* s ="hello";
bar(a);
bar(s);
}
#包括
#包括
模板
结构包裹
{
常数T&value;
包裹(常数T和值)
:值(value)
{}
};
模板
内联换行(常量T和值){
返回包装(值);
}
模板
空心条(常数包裹&){
std::cout(在这里回答自己的问题)。我不太擅长这个重载解析和断开连接。我的答案一般正确吗?欢迎反馈!@PiotrS。谢谢,我也删除了我对\uu PRETTY\u函数的使用。我发现它在调试中非常有用,但它不是标准的。这不适用于非常量值。例如char*s;bar
。我想主要的一点是,我不想只寻找参数的完美匹配。各种类型的转换总是有余地的。我希望bar1
具有优先级,并且只有在编译器确定无论转换如何都不能调用bar1
之后,才应该将其移动到bar2
。最后,与您的答案相关的是,如果bar1
被拒绝,我希望编译器尽力调用bar2
。我不希望bar2
失败,因为它没有注意到它可以将char*
转换为const char*
。
try_bar1_then_bar2("hello"); // array, calls array version
try_bar1_then_bar2(+"hello"); // + converts to a pointer, therefore
// this calls the pointer ('raw') version.
#include <cstring>
#include <iostream>
template <typename T>
struct Wrap
{
const T& value;
Wrap(const T& value)
: value(value)
{}
};
template <typename T>
inline Wrap<T> wrap(const T& value) {
return Wrap<T>(value);
}
template <size_t N>
void bar(const Wrap<char[N]>&) {
std::cout << "array, size=" << N-1 << std::endl;
}
void bar(const Wrap<const char *>& s) {
std::cout << "raw, size=" << strlen(s.value) << std::endl;
}
template <typename T>
void bar(const T& value) {
bar(wrap(value));
}
int main(int argc, char* argv[]) {
const char a[] ="hello";
const char* s ="hello";
bar(a);
bar(s);
}