c++ - 有没有办法使用 SFINAE 检测是否未声明非模板化非成员函数?

标签 c++ templates c++11 sfinae decltype

我正在尝试回答 this question使用 SFINAE 和 decltype。总而言之,发布者想要一个函数,该函数的行为取决于是否在编译单元中声明了另一个函数(声明早于或晚于所讨论的函数)。

我尝试了以下方法:

auto some_function_2_impl(int) -> decltype(some_function_1(), void()) {
    cout << "Using some_function_1" << endl;
    some_function_1();
}

void some_function_2_impl(long) {
    cout << "Not using some_function_1" << endl;
}

void some_function_2() {
    return some_function_2_impl(0);
}   

但是,我收到此错误消息:

main.cpp:4:60: error: 'some_function_1' was not declared in this scope
 auto some_function_2_impl(int) -> decltype(some_function_1(), void()) {

这就是重点,我想 - 我不想定义 some_function_2_impl 的重载,因为 some_function_1 不存在。

我想也许 SFINAE 需要模板才能工作,所以我尝试了以下操作(这可能有助于表明我并不完全知道我在这里做什么):

template <int foo>
auto some_function_2_impl(int) -> decltype(some_function_1(), void()) {
    cout << "Using some_function_1" << endl;
    some_function_1();
}

template <int foo>
void some_function_2_impl(long) {
    cout << "Not using some_function_1" << endl;
}

但是,现在我收到以下错误:

main.cpp:5:60: error: there are no arguments to 'some_function_1' that 
depend on a template parameter, so a declaration of 'some_function_1'
must be available [-fpermissive]
 auto some_function_2_impl(int) -> decltype(some_function_1(), void()) {

我做错了什么?

最佳答案

函数查找会立即完成,即使在模板类型中也是如此,除非可能根据模板参数类型进行 ADL 查找。

然后在替换类型后进行 ADL 查找。如果失败,则结果为替换失败。

由于您的函数调用不依赖于参数类型,因此该技术不起作用。

我们仍然可以做一些适度有趣的事情:

template<class T, class...Ts>
struct first_two_match : std::false_type{};
template<class T, class...Ts>
struct first_two_match<T,T,Ts...>:std::true_type{}; // for standard compliance: If the only Ts... that match Ts... is nothing, program ill-formed.
struct secret_type_tag {};
template<class...Ts,
  std::enable_if_t<
    (sizeof...(Ts)==0) || first_two_match<secret_tag_type,Ts...>{}
  >* =nullptr
>
secret_type_tag some_function_1(Ts&&...);

template<bool b>
using bool_t=std::integral_constant<bool, b>;
static const auto some_function_defined = bool_t<
  !std::is_same<secret_tag_type, decltype( some_function_1() )>{}
>;

现在 some_function_definedstd::true_type 当且仅当存在 some_function_1 的重载比我的 some_function_1(Ts&&. ..)。由于 some_function_1(Ts&&...) 的优先级非常低,因此任何“真正的”重载(它也不是转发引用 glomer 并且采用 0 个参数)将是首选。

在更复杂的情况下,如果存在真正的过载,那么从不选择如此低优先级的过载是很棘手的。

仍然 只是检测是否在创建 some_function_defined 的位置定义了 some_function_1。骗子。

关于c++ - 有没有办法使用 SFINAE 检测是否未声明非模板化非成员函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32631880/

相关文章:

c++ - 模板 "copy constructor"不阻止编译器生成的移动构造函数

c++ - 调用 vkEnumerateDeviceExtensionProperties "twice"- 是否需要?

c++ - 自定义排序和映射时更喜欢函数指针还是函数对象?

c++ - 围绕 boost::ptree 头痛的模板化类

c++ - 制作可变参数异常构造函数以填充字符串流

c++ - 为什么 C++11 不支持这样的名称查找?

c++ - 设置插入进行奇怪数量的比较

c++ - 获取迭代次数?

c++ - 我需要哪个 SDK 来确保 Visual Studio C++ 2017 中的 Windows 7 兼容性

C++11 从变量中获取 std::map value_type