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

C++ 重载函数以接受模板指针变量,c++,templates,pointers,overloading,C++,Templates,Pointers,Overloading,在main函数中调用push方法时使用它。但是,即使主函数中的参数是指针,它仍然使用函数void Push(const DATA\u TYPE&newValue) 它不应该使用另一个,因为它是接受指针的那个吗?如果存在指针变量,如何更改第二个函数中的参数以覆盖该函数 template<typename DATA_TYPE> void Push(const DATA_TYPE& newValue) { //do stuff } template<typen

在main函数中调用push方法时使用它。但是,即使主函数中的参数是指针,它仍然使用函数
void Push(const DATA\u 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
}
模板
无效推送(常量数据类型和新值)
{
//做事
}
模板
无效推送(常量数据类型*新值)
{
//做事
}

我已经测试了这个程序

#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;
}

你的问题在于康斯特内斯

问题是,当您使用非常量对象指针调用
Push(p)
时,
p*p
第一个版本在设置数据类型=
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 );
}
#包括
福班
{
公众:
模板
无效推送(常数DT和新值)
{

std::cout这是因为
const DATA\u TYPE&newValue
几乎可以匹配任何东西,在您的情况下,它匹配指针
const DATA\u TYPE*&newValue
。尝试使用
std::remove\u 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
}

这正如预期的那样工作,它不会强制调用方使用适当的常量,尽管我承认它没有我以前的解决方案那么吸引人;)

这里的区别是
模板无效推送(t*)
是一个模板,其中
无效推送(const DATA_TYPE*newValue)
不是。我看不出这与问题有什么关系。缺少的
常量
&x
是一个右值,不能绑定到
非常量
参考。您可能已经澄清,这意味着参考版本提供了精确匹配,但指针版本仍然需要从
非常量
进行类型转换到
const
指针,所以参考版本更匹配。@Keith我同意,希望我现在已经充分说明了这一点。似乎你不能用那种方式进行参数类型推断:看看所有的内容都解释得很好。
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
}
#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;
}