首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SFINAE误差

SFINAE误差
EN

Stack Overflow用户
提问于 2016-03-28 18:27:06
回答 1查看 95关注 0票数 2

为什么以下代码会导致错误?我认为编译器只是在这里选择适当的重载吗?

代码语言:javascript
复制
#include <iostream>
using std::cout;
using std::endl;

template <typename ToCheckFor>
struct InterfaceCheck {

    // used by the constexpr function, the function will pass in a pointer to
    // a type with the required types
    template <typename _ToCheckFor, void (_ToCheckFor::*) ()>
    struct InterfaceCheckImplTag {};

    // used to check for the presence of a function print()
    // template <typename T>
    // static constexpr bool function(__attribute__((unused)) void* ptr) {}
    template <typename T>
    static constexpr bool function(__attribute__((unused)) void* ptr) { 
        return false; 
    }
    template <typename T>
    static constexpr bool function (__attribute__((unused))  
         InterfaceCheckImplTag<T, &T::print>* ptr) { 

        return true; 
    }

    constexpr static const bool value = function<ToCheckFor>(nullptr);
};

struct Something {
    void print() { cout << "Something::print()" << endl; }
};

int main() {

    cout << InterfaceCheck<Something>::value << endl;

    return 0;
}

为什么用省略号替换void*参数使代码像预期的那样工作呢?因此,下面的代码按预期工作

代码语言:javascript
复制
#include <iostream>
using std::cout;
using std::endl;

template <typename ToCheckFor>
struct InterfaceCheck {

    // used by the constexpr function, the function will pass in a pointer to
    // a type with the required types
    template <typename _ToCheckFor, void (_ToCheckFor::*) ()>
    struct InterfaceCheckImplTag {};

    // used to check for the presence of a function print()
    // template <typename T>
    // static constexpr bool function(__attribute__((unused)) void* ptr) {}
    template <typename T>
    static constexpr bool function(...) { 
        return false; 
    }
    template <typename T>
    static constexpr bool function (__attribute__((unused))  
         InterfaceCheckImplTag<T, &T::print>* ptr) { 

        return true; 
    }

    constexpr static const bool value = function<ToCheckFor>(nullptr);
};

struct Something {
    void print() { cout << "Something::print()" << endl; }
};

int main() {

    cout << InterfaceCheck<Something>::value << endl;

    return 0;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-28 18:38:07

为什么以下代码会导致错误?

对于function重载有两种可行的选择。这两种方法都涉及从所提供的参数进行转换,而且这两种转换都优于另一种:

代码语言:javascript
复制
error: call to 'function' is ambiguous
    constexpr static const bool value = function<ToCheckFor>(nullptr);
                                        ^~~~~~~~~~~~~~~~~~~~
test.cpp:36:13: note: in instantiation of template class 'InterfaceCheck<Something>' requested here
    cout << InterfaceCheck<Something>::value << endl;
            ^
test.cpp:17:27: note: candidate function [with T = Something]
    static constexpr bool function(__attribute__((unused)) void* ptr) { 
                          ^
test.cpp:21:27: note: candidate function [with T = Something]
    static constexpr bool function (__attribute__((unused))  

使用function(...)进行修复是有效的,因为从任何东西到...的转换总是比其他任何东西都“更糟糕”(但仍然合法)。一旦你知道了这是个绝妙的把戏。

从13.3.3.2排序隐式转换序列over.ics.rank

  1. 当比较隐式转换序列的基本形式时(如13.3.3.1所定义)
代码语言:javascript
复制
- a standard conversion sequence (13.3.3.1.1) is a better conversion sequence than a user-defined conversion sequence or an ellipsis   conversion sequence, and
- a user-defined conversion sequence (13.3.3.1.2) is a better conversion sequence than an ellipsis conversion sequence   (13.3.3.1.3).

历史

我第一次从现代C++设计第2.7节学到了这个技巧。我不知道这是否是发明它的地方。但这也不是个糟糕的猜测。这本书现在已有15年历史了,它仍然是一本很好的读物。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36268560

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档