C++通过const引用传递一个const指针

use*_*168 6 c++ const

在VC2012中我是一个奇怪的人我似乎无法弄清楚通过const引用将const指针传递给模板化参数的函数的语法,模板参数是非常量指针,即:

template<typename T>
struct Foo
{
    void Add( const T& Bar ) { printf(Bar); }
};

void main()
{
Foo<char*> foo;
const char* name = "FooBar"; 
foo.Add(name);                 // Causes error
}
Run Code Online (Sandbox Code Playgroud)

所以我在这里简化了我的问题,但基本上我希望参数'Add'有一个const T即const char*.我试过了:

void Add( const (const T)& Bar ); 

typedef const T ConstT;
void Add( const (ConstT)& Bar );  

void Add( const typename std::add_const<T>::type& Bar ); 
Run Code Online (Sandbox Code Playgroud)

这些都不起作用.我得到的确切错误是:

error C2664: 'Foo<T>::Add' : cannot convert parameter 1 from 'const char *' to 'char *const &'
          with
          [
              T=char *
          ]
          Conversion loses qualifiers 
Run Code Online (Sandbox Code Playgroud)

我可以看到它是正确的,但如何解决它没有常量'name'为非const.

Dav*_*eas 8

指向常量对象(T const*const T*)的指针与指向非常量对象(T * const)的常量指针之间存在很大差异.在您的情况下,该成员的签名Add是:

void Foo<char *>::Add(char * const& ); // reference to a constant pointer to a 
                                       // non-constant char
Run Code Online (Sandbox Code Playgroud)

const出于这个原因,我通常建议人们完全放弃使用左侧,因为初学者通常会将typedefs(或推断类型)与类型替换混淆,当他们阅读时:

const T& [T == char*]
Run Code Online (Sandbox Code Playgroud)

他们误解了

const char*&
Run Code Online (Sandbox Code Playgroud)

如果const放在正确的地方:

T const &
Run Code Online (Sandbox Code Playgroud)

简单的心理替代工作对初学者来说更简单:

char * const &
Run Code Online (Sandbox Code Playgroud)

一个不同于你所问的问题,但也许你认为你想要的是:

给定一个类型T有一个函数,需要一个U就是const T,如果T不是指针类型,或者X const *如果T是一个指针X

template <typename T>
struct add_const_here_or_there {
    typedef T const type;
};
template <typename T>
struct add_const_here_or_there<T*> {
    typedef T const * type;
};
Run Code Online (Sandbox Code Playgroud)

然后你可以在签名中使用它:

template <typename T>
void Foo<T>::Add( const typename add_const_here_or_there<T>::type & arg ) {
     ...
Run Code Online (Sandbox Code Playgroud)

请注意,我const在签名中添加了两个,因此在您的情况下char*将映射到char const * const &,因为您似乎想要传递const&给某个东西,并且您还希望指向类型const.

您可能想知道元函数的名称:*add_const_here_or_there*,它就像是有原因:没有简单的方法来描述您尝试做什么,这通常是代码味道.但在这里你有解决方案.


Mar*_*k B 3

这看起来像是你的问题,因为一旦你将指针类型映射到模板类型,你就不能再向指向的类型添加常量,只能向指针本身添加常量。您想要做的就是自动将常量添加到函数的参数中(因此,如果 T 是char*函数应该接受const char* const&而不是char* const&像您编写的那样)。做到这一点的唯一方法是使用另一个模板为指针类型的指针添加常量,如下所示。我冒昧地包含了丢失的标头并更正了以下签名main

#include <cstdio>

template<typename T>
struct add_const_to_pointee
{
    typedef T type;
};

template <typename T>
struct add_const_to_pointee<T*>
{
    typedef const T* type;
};

template<typename T>
struct Foo
{
    void Add( typename add_const_to_pointee<T>::type const & Bar ) { printf(Bar); }
};

int main()
{
    Foo<char*> foo;
    const char* name = "FooBar";
    foo.Add(name);                 // Causes error
}
Run Code Online (Sandbox Code Playgroud)

std::string然而,正如另一篇文章中提到的,如果您使用而不是 C 样式字符串,这个问题就会消失。