const char*、const char(&)[N] 和 std::string 的函数重载

Posted

技术标签:

【中文标题】const char*、const char(&)[N] 和 std::string 的函数重载【英文标题】:Function overloading for const char*, const char(&)[N] and std::string 【发布时间】:2016-01-05 21:38:49 【问题描述】:

我想要实现的是重载适用于字符串文字和std::string 的函数,但会为const char* 参数产生编译时错误。以下代码几乎可以满足我的要求:

#include <iostream>
#include <string>

void foo(const char *& str) = delete;

void foo(const std::string& str) 
    std::cout << "In overload for const std::string&     : " << str << std::endl;


template<size_t N>
void foo(const char (& str)[N]) 
    std::cout << "In overload for array with " << N << " elements : " << str << std::endl;
   

int main() 
    const char* ptr = "ptr to const";
    const char* const c_ptr = "const ptr to const";
    const char arr[] = "const array";
    std::string cppStr = "cpp string";

    foo("String literal");
    //foo(ptr); //<- compile time error
    foo(c_ptr); //<- this should produce an error
    foo(arr);   //<- this ideally should also produce an error
    foo(cppStr);

我很不高兴,它为 char 数组变量编译,但我认为如果我想接受字符串文字就没有办法(如果有,请告诉我)

然而,我想避免的是 std::string 重载接受 const char * const 变量。不幸的是,我不能只声明一个带有 const char * const&amp; 参数的已删除重载,因为它也会匹配字符串文字。

任何想法,我怎样才能让foo(c_ptr) 产生编译时错误而不影响其他重载?

【问题讨论】:

char 数组的类型和字符串字面量的类型之间没有区别,所以你不能没有一个就扔掉一个。但我认为你的其他要求是可以满足的。 @Tavian Barns:我想知道,如果有人可以使用字符串文字也是一个常量表达式这一事实(当然你也可以创建一个 constexpr 数组) 【参考方案1】:

此代码执行所需的操作(数组除外 - 文字是数组,因此您无法将它们分开)

#include <cstddef>
#include <string>

template <class T>
void foo(const T* const & str) = delete;

void foo(const std::string& str);

template<std::size_t N>
void foo(const char (& str)[N]);

int main() 
    const char* ptr = "ptr to const";
    const char* const c_ptr = "const ptr to const";
    const char arr[] = "const array";
    std::string cppStr = "cpp string";

    foo("String literal");
    //foo(ptr); //<- compile time error
    // foo(c_ptr); //<- this should produce an error
    foo(arr);   //<- this ideally should also produce an error
    foo(cppStr);

【讨论】:

谢谢。有了那个模板函数,我相信第一个重载(const char *&amp; str)不再需要了——对吧?【参考方案2】:

为了使您的删除函数比模板函数更好地匹配,以便字符串文字仍然有效,删除的函数也需要是模板。这似乎满足您的要求(尽管仍然允许使用数组):

template <typename T>
typename std::enable_if<std::is_same<std::decay_t<T>, const char*>::value>::type
foo(T&& str) = delete;

Demo.

【讨论】:

...我本来打算这样做,但你打败了我:) 这里不需要 SFINAE。 谢谢,我总是忘记这一点【参考方案3】:

在该语言的现代版本中,您可以创建一些自定义类型和用户定义的文字来创建它,这样就可以传递"this"_SOMEWORDS,而不仅仅是 c 字符串文字、聊天指针或字符数组。

它并不能完全满足您传递字符串文字的要求,但我认为它已经足够好了,尤其是因为它还禁止数组

【讨论】:

这实际上是一个非常有趣的想法,因为它允许人们区分字符数组和字符串文字。但这并不妨碍std::string 重载接受const char * const 参数。 @MikeMB 现在只需删除它(const char* 重载)就可以了 对 - 抱歉,来晚了。是否可以通过这种方式在编译时获取字符串文字的长度(如在我的带有模板参数的示例函数中)? @MikeMB,不幸的是我当时没能做到。似乎模板形式仅适用于整数/浮动文字 没问题,这不是硬性要求。再次感谢。到目前为止,我只在一些玩具示例中使用了用户定义的文字,只是没有考虑手头的问题。

以上是关于const char*、const char(&)[N] 和 std::string 的函数重载的主要内容,如果未能解决你的问题,请参考以下文章

char * const * (*a) (int b)

深入理解const char*p,char const*p,char *const p,const char **p,char const**p,char *const*p,char**const p

深入理解const char*p,char const*p,char *const p,const char **p,char const**p,char *const*p,char**cons(示例

const char **,char *const *,char ** const

[转载] C++ string, const char*, char* 之间互相转换

string,const char*, char*转换之后还是指向同一片内存地址么?