首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C++:构造函数仅接受字符串文字

C++:构造函数仅接受字符串文字
EN

Stack Overflow用户
提问于 2010-01-11 19:03:06
回答 6查看 6.2K关注 0票数 20

是否可以创建一个只接受字符串文字,而不接受char const *的构造函数(或函数签名

是否可以有两个重载来区分字符串文字和char const *

C++ 0x会允许使用自定义后缀,但我正在寻找一个“更早”的解决方案。

基本原理:避免将字符串作为字符串文字提供时不会修改的字符串的堆副本。

这些字符串不经过任何处理,直接转到需要const char *的接口。大多数调用都使用不需要额外处理的文字,只有在少数情况下才会构造它们。我正在寻找一种保留本机调用行为的可能性。

注意:-因为它出现在答案中:所讨论的代码根本不使用std::string,但一个很好的例子是:

class foo
{
   std::string m_str;
   char const * m_cstr;      
 public:
   foo(<string literal> s) : m_cstr(p) {}
   foo(char const * s) : m_str(s) { m_cstr = s.c_str(); }
   foo(std::string const & s) : m_str(s) { m_cstr = s.c_str(); }

   operator char const *() const { return m_cstr; }
}

结果:

(1)做不到。

(2)我意识到我甚至不是在寻找文字,而是在寻找编译时间常量(即“任何不需要复制的东西”)。

我可能会使用以下模式:

const literal str_Ophelia = "Ophelia";

void Foo()
{
  Hamlet(str_Ophelia, ...);  // can receive literal or string or const char *
}

使用一个简单的

struct literal  
{ 
   char const * data; 
   literal(char const * p) : data(p) {} 
   operator const char *() const { return data; }
};

这并不能阻止任何人滥用它(我应该找一个更好的名字...),但它允许进行所需的优化,但在默认情况下仍然是安全的。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-01-11 19:06:57

不,你不能这样做--字符串和常量字符*是可以互换的。一种解决办法是引入一个特殊的类来保存指向字符串文字的指针,并使构造函数只接受这一点。这样,无论何时需要传递文字,都可以调用该类的构造函数并传递临时对象。这并不能完全防止误用,但使代码更易于维护。

票数 9
EN

Stack Overflow用户

发布于 2010-01-11 20:19:29

基于sbi idea的工作解决方案

struct char_wrapper
{
    char_wrapper(const char* val) : val(val) {};
    const char* val;
};

class MyClass {
public:
  template< std::size_t N >
  explicit MyClass(const char (&str)[N])
  {
      cout << "LITERAL" << endl;
  }
  template< std::size_t N >
  explicit MyClass(char (&str)[N])
  {
      cout << "pointer" << endl;
  }    
  MyClass(char_wrapper m)
  {
     cout << "pointer" << endl;
  }
};

int main()
{
    MyClass z("TEST1");     // LITERAL
    const char* b = "fff";
    MyClass a(b);           // pointer
    char tmp[256]; 
    strcpy(tmp, "hello"); 
    MyClass c(tmp);         // pointer
}
票数 20
EN

Stack Overflow用户

发布于 2014-06-19 08:18:53

是的,it can be be!我想出了一个使用C++03的解决方案,并且没有包装器类(它打破了返回语句中的一些隐式转换)。

首先,您需要一个用于类型const char (&)[N]的构造函数模板,因为这是字符串文字的原始类型。然后,您还需要另一个用于char (&)[N]类型的函数-例如,类似于char buffers -这样它们就不会在文字的构造函数中结束。而且您可能还需要一个用于const char*类型的普通构造函数。

template<int N> Foo(const char (&)[N]); // for string literals
template<int N> Foo(char (&)[N]);       // for non-const char arrays like buffers
Foo(const char*);                       // normal c strings

现在的问题是,对于字符串文字,编译器仍然认为const char*构造函数是比模板实例更好的选择,因为数组到指针的转换具有精确匹配的等级。(13.3.3.1.1)

所以,诀窍是降低const char*构造函数的优先级。这可以通过将其更改为模板并使用SFINAE将其仅与类型const char*进行匹配来实现。构造函数没有返回值,并且只有一个参数,这是类型推导所必需的。因此,另一个使用默认值的“伪参数”是必需的,它使用条件类型特征:template<typename T> Foo(T, typename IsCharPtr<T>::Type=0)

解决方案:

#include <iostream>

#define BARK std::cout << __PRETTY_FUNCTION__ << std::endl

struct Dummy {};
template<typename T> struct IsCharPtr {};
template<> struct IsCharPtr<const char *> { typedef Dummy* Type; };
template<> struct IsCharPtr<char *> { typedef Dummy* Type; };

struct Foo {
  template<int N> Foo(const char (&)[N]) { BARK; }
  template<int N> Foo(char (&)[N]) { BARK; }
  template<typename T> Foo(T, typename IsCharPtr<T>::Type=0) { BARK; }
};

const char a[] = "x";
const char* b = "x";
const char* f() { return b; }

int main() {
  char buffer[10] = "lkj";
  char* c = buffer;
  Foo l("x");     // Foo::Foo(const char (&)[N]) [N = 2]
  Foo aa(a);      // Foo::Foo(const char (&)[N]) [N = 2]
  Foo bb(b);      // Foo::Foo(T, typename IsCharPtr<T>::Type) [T = const char *]
  Foo cc(c);      // Foo::Foo(T, typename IsCharPtr<T>::Type) [T = char *]
  Foo ee(buffer); // Foo::Foo(char (&)[N]) [N = 10]
  Foo ff(f());    // Foo::Foo(T, typename IsCharPtr<T>::Type) [T = const char *]
  return 0;
}
票数 19
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2041355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档