重载函数以接受模板指针变量

Overloading a function to accept a template pointer variable

本文关键字:指针 变量 函数 重载      更新时间:2023-10-16

push方法在main函数中调用时使用。然而,即使main函数中的参数是指针,它仍然使用函数void Push(const DATA_TYPE& newValue)

它不应该使用另一个,因为它是接受指针的那个吗?我如何改变第二个函数的参数,以覆盖一个,如果有一个指针变量?

template<typename DATA_TYPE>   
void Push(const DATA_TYPE& newValue)
{
    //do stuff
}
template<typename DATA_TYPE> 
void Push(const DATA_TYPE *newValue)
{
    //do stuff
}

你的问题是不稳定。

问题是,当您使用非const对象指针调用Push(p)时,P * p的第一个版本恰好在设置DATA_TYPE= P*时工作,给出Push( const P* & )的函数签名。相比之下,DATA_TYPE= P的第二个版本需要将const添加到类型签名中以获得Push( const P* )。这意味着选择第一个版本而不是第二个版本,因为它是精确匹配的。

这里有一个例子来说明发生了什么:

下面是一个例子:

#include <iostream>
class Foo
{
    public:
    template<typename DT>   
    void Push(const DT& newValue)
    {
        std::cout<<"In const DT& version"<<std::endl;
    }
    template<typename DT>
    void Push(const DT *newValue)
    {
        std::cout<<"In const DT* version"<<std::endl;
    }
};
int main()
{
    Foo f;
    int i=7;
    // Since i is not const we pickup the wrong version
    f.Push( i ); // const DT&  ( DT = int )
    f.Push( &i ); // const DT& ( DT = int* )
    // Here's using a const pointer to show it does the right things
    const int * const_i_ptr = &i;
    f.Push( const_i_ptr ); // const DT* ( DT = int );
    // Now using a const object everything behaves as expected
    const int i_const = 7;
    f.Push( i_const ); // const DT& ( DT = int );
    f.Push( &i_const ); // const DT*  (DT = int );
}

我已经测试了这个程序

#include <iostream>
template <typename T>
void push(T&)
{
    std::cout << "By ref" << std::endl;
}
template <typename T>
void push(T*)
{
    std::cout << "By ptr" << std::endl;
}
int main()
{
    int x = 0;
    push(x);
    push(&x);
    return 0;
}

输出
By ref
By ptr

这是因为const DATA_TYPE& newValue将匹配几乎任何东西,在您的情况下,它匹配指针const DATA_TYPE*& newValue的引用。尝试使用这里描述的std::remove_pointer -从我的头顶,我会写:

template<typename DATA_TYPE>   
void Push(const typename std::remove_pointer<DATA_TYPE>::type& newValue)
{
    //do stuff
}
template<typename DATA_TYPE> 
void Push(const DATA_TYPE *newValue)
{
    //do stuff
}

不,然而,编写匹配const T&的模板以及其他模板重载通常会导致const T&抓取每个调用,所以你应该避免这样做。

编辑:

我之前的代码是不正确的,它必须更复杂一点:

#include <iostream>
#include <type_traits>
template<typename DATA_TYPE, bool is_pointer>
struct helper;
template<typename DATA_TYPE>
struct helper<DATA_TYPE, true>{
    static void f(const typename std::remove_pointer<DATA_TYPE>::type*){
        std::cout << "Pointer" << std::endl;
    }
};
template<typename DATA_TYPE>
struct helper<DATA_TYPE, false>{
    static void f(const DATA_TYPE&){
        std::cout << "Non-pointer" << std::endl;
    }
};
template<typename DATA_TYPE>
void Push(const DATA_TYPE& newValue)
{
    helper<DATA_TYPE, std::is_pointer<DATA_TYPE>::value >::f(newValue);
}
int main()
{
    int i=0;
    Push(i);
    Push(&i);
    return 0;
}

这是预期的工作,它不强迫调用者使用适当的const-ness,虽然我承认它不像我以前的解决方案那样迷人;)