Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 强制先尝试一个过载,然后再尝试另一个过载_C++_Templates_Sfinae - Fatal编程技术网

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);
}