在模板函数中传递名称查找

有没有办法强制C ++编译器在模板实例化(而不是之前)中为给定的符号执行名称查找?

给出以下代码:

template <class T>
auto wrapper( T t ) -> decltype( f( t ) )
{
    return f( t );
}

unsigned char f( int x ) { return x % 256; }
unsigned char f( unsigned char x ) { return x; }

int main( int, char ** )
{
    auto x = wrapper( 3100 );
    return 0;
}

有什么我可以做的(除了将f的定义移到顶部),以便使代码编译并给出相同的结果,就好像f所有定义在wrapper的定义之前都可用一样?

我找不到任何东西,可能是因为我不知道如何恰当地说出这个问题。 如果有帮助, f所有参数类型都可以假定为用户定义的类型。


有没有办法强制C ++编译器在模板实例化(而不是之前)中为给定的符号执行名称查找?

是。 首先,这个名字必须是依赖的。 用作f(t)时, wrapper的名称f是相关的,因为t是依赖于类型的。 [temp.dep] / 1:

在一个表达式中:

postfix-expression (表达式列表选择)

在postfix-expression是一个非限定的id的情况下,unqualified-id表示一个依赖的名字if

  • 表达式列表中的任何表达式都是包扩展(14.5.3),
  • 表达式列表中的任何表达式都是与类型相关的表达式(14.6.2.2) ,或者
  • 如果unqualified-id是一个template-id,其中任何模板参数都依赖于模板参数。
  • 问题是在模板本身之后声明的名称,即仅在实例化中声明,而不在定义上下文中,可以使用参数相关名称查找来单独找到。 根据[basic.lookup.argdep] / 2,你的f重载只包含基本类型,但是它们没有与它们关联的全局名称空间:

    如果T是基本类型,则其关联的命名空间和类都是空的。

    因此,如果参数与参数的类型相同,那么您声明的f永远不会被找到。 一个小技巧可以帮助:

    template <typename T>
    struct refwrap
    {
        T&& t;
        refwrap(T&& t) : t(std::forward<T>(t)) {}
        operator T&&() {return std::forward<T>(t);}
    };
    
    template <typename T>
    auto make_refwrap( T&& t ) -> refwrap<T> // making use of reference collapsing
    { return {std::forward<T>(t)}; }         // inside refwrap to get forwarding
    

    此模板在全局名称空间中声明时,将导致ADL考虑它。 重写wrapper如下:

    template <class T>
    auto wrapper( T t ) -> decltype( f( make_refwrap(t) ) )
    {
        return f( make_refwrap(t) );
    }
    

    演示 。 这不是正确的方法,因为它会在更复杂的情况下失败。


    这将与模板专业化一起工作。 请注意,您必须决定默认功能是什么,因为我看不到有问题。

    // default function
    template <class T>
    unsigned char f( T x ) { return x; }
    
    // specialization for int
    template <>
    unsigned char f( int x ) { return x % 256; }
    
    int main( int, char ** )
    {
        auto x = f( 3100 );
        return 0;
    }
    

    下面的代码不是很干净,但说明了如何使用类模板专门化来解决问题。 它保持原始接口(即fwrapper可以像以前一样使用)。

    谢谢你给我正确的提示。 我接受了一个不太详细的解决方案。

    #include <type_traits>
    
    template <class ...>
    struct F;
    
    template <class T>
    auto wrapper( T t )
        -> decltype( F<typename std::decay<T>::type>::f( t ) )
    {
        return F<typename std::decay<T>::type>::f( t );
    }
    
    template <>
    struct F<unsigned char>
    {
        static unsigned char f( unsigned char x ) { return x; }
    };
    
    template <>
    struct F<int>
    {
        static unsigned char f( int x ) { return x % 256; }
    };
    
    template <class T>
    auto f( T t )
        -> decltype( F<typename std::decay<T>::type>::f( t ) )
    {
        return F<typename std::decay<T>::type>::f( t );
    }
    
    int main( int, char ** )
    {
        auto x = wrapper( 3100 );
        return 0;
    }
    
    链接地址: http://www.djcxy.com/p/24487.html

    上一篇: pass name lookup in template function

    下一篇: How to ignore hidden elements in a Bootstrap Button Group?