简体   繁体   English

对于带有附加(非推断)模板参数的函数,ADL是否失败(或未完成?)

[英]ADL fails (or not done?) for function with additional (non deduced) template parameter

namespace N {
    class C {};

    template<typename X>
    char const * found(X && x) {
        return "found";
    }

    template<typename, typename X>
    char const * notfound(X && x) {
        return "not found";
    }
}

This defines a namespace N with a class C and two function templates. 这定义了具有类C和两个函数模板的名称空间N found has a single template parameter, which can be deduced from the function argument. found有一个模板参数,可以从函数参数中推导出来。 notfound has an additional template parameter which cannot be deduced. notfound有一个额外的模板参数,无法推断出来。

Given following test code ( on ideone ): 给出以下测试代码( 在ideone上 ):

#include <iostream>
int main() {
    N::C object;
    std::cout
        << found(object) << std::endl
        << notfound<bool>(object) << std::endl  // ERROR
        << notfound<bool, N::C>(object) << std::endl; // ERROR
}

I assumed that argument dependent lookup would find both found and notfound through the innermost enclosing namespace (which is N ) of the argument type N::C . 我假定参数依赖查找会发现二者foundnotfound通过最内层的命名空间(这是N参数类型的) N::C

However: 然而:

prog.cpp: In function ‘int main()’:
prog.cpp:21:6: error: ‘notfound’ was not declared in this scope
   << notfound<bool>(object) << std::endl
      ^~~~~~~~
prog.cpp:21:6: note: suggested alternative:
prog.cpp:12:15: note:   ‘N::notfound’
  char const * notfound(X && x) {
               ^~~~~~~~

(same error for notfound<bool, N::C>(object) after commenting out the notfound<bool>(object) call) (注释掉未notfound<bool>(object)调用后,未notfound<bool, N::C>(object)错误相同)

Why is notfound not found through ADL? 为什么notfound通过ADL发现?


Background: I'm implementing a get function for some wrapper class, all in all relatively similar to std::get(std::tuple) . 背景:我正在为一些包装类实现一个get函数,所有这些都与std::get(std::tuple)相似。 The wrapper class, being an implementation detail, lives in some namespace lib::aspect::part::impl . 包装类是一个实现细节,它位于一些名称空间lib::aspect::part::impl I don't want users of the library to specify using lib::aspect::part::impl::get for obvious reasons. 我不希望库的用户指定using lib::aspect::part::impl::get ,原因很明显。

Because a function call to a function template with explicitly-specified template arguments requires the name of the template must be found by ordinary lookup; 因为函数调用具有显式指定的模板参数的函数模板,所以必须通过普通查找找到模板的名称; until that ADL can't kick in. 直到那个ADL无法启动。

From the standard: $17.8.1/8 Explicit template argument specification [temp.arg.explicit] 来自标准: $ 17.8.1 / 8显式模板参数规范[temp.arg.explicit]

(emphasis mine) (强调我的)

[ Note: For simple function names, argument dependent lookup applies even when the function name is not visible within the scope of the call. [注意:对于简单的函数名称,即使函数名称在调用范围内不可见,依赖于参数的查找也适用。 This is because the call still has the syntactic form of a function call ([basic.lookup.unqual]). 这是因为调用仍然具有函数调用的句法形式([basic.lookup.unqual])。 But when a function template with explicit template arguments is used, the call does not have the correct syntactic form unless there is a function template with that name visible at the point of the call . 但是当使用带有显式模板参数的函数模板时,除非在调用点处有一个具有该名称的函数模板,否则调用没有正确的语法形式 If no such name is visible, the call is not syntactically well-formed and argument-dependent lookup does not apply. 如果看不到这样的名称,则调用语法不完善,并且参数依赖查找不适用。 If some such name is visible, argument dependent lookup applies and additional function templates may be found in other namespaces. 如果某些此类名称可见,则应用依赖于参数的查找,并且可以在其他名称空间中找到其他函数模板。 [ Example: [例如:

 namespace A { struct B { }; template<int X> void f(B); } namespace C { template<class T> void f(T t); } void g(A::B b) { f<3>(b); // ill-formed: not a function call A::f<3>(b); // well-formed C::f<3>(b); // ill-formed; argument dependent lookup applies only to unqualified names using C::f; f<3>(b); // well-formed because C​::​f is visible; then A​::​f is found by argument dependent lookup } 

— end example ] — end note ] - 结束例子] - 结束说明]

The last sentence gives a possible workaround; 最后一句给出了可能的解决方法; you can add the declaration of the function template anywhere to make the name visible for being called. 您可以在任何位置添加函数模板的声明,以使名称对于被调用是可见的。 eg 例如

template<typename>
void notfound();

int main() {
    N::C object;
    std::cout
        << found(object) << std::endl
        << notfound<bool>(object) << std::endl
        << notfound<bool, N::C&>(object) << std::endl; // btw the 2nd template argument should be N::C&
}

LIVE 生活

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在函数中推导出参数之前的默认模板参数? - Default template parameter before deduced parameter in a function? 涉及非推导参数包的函数指针的参数类型的模板参数推导 - Template arguments deduction for parameter type of function pointer involving non-deduced parameter pack 推导模板参数顺序? - Deduced template parameter order? 无法推导模板参数 - Template parameter cannot be deduced 推导(非类型)模板参数类型的编译器差异 - Compiler variance for the type of deduced (non-type) template parameter 使用已经推导出的模板参数来专门化模板成员函数 - Specialize template member function with already-deduced template parameter 可以从指向成员函数模板参数的指针推导出类类型 - Can class type be deduced from pointer to member function template parameter 为什么std :: function不能接受推导类型作为模板参数? - Why can std::function not accept a deduced type as its template parameter? 为什么不能在函数中使用模板别名作为参数并自动推导? - Why is it not possible to use a template alias in function as parameter and to be automatically deduced? `std::function` 和之前推导出的模板参数替换失败 - 为什么? - Substitution failure with `std::function` and previously deduced template parameter - why?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM