【问题标题】:Overload char pointers and string literals重载 char 指针和字符串文字
【发布时间】:2014-12-21 15:36:57
【问题描述】:

我正在尝试创建一个类,该类将接受(并且可以消除歧义)来自 char 指针的字符串文字。在搜索这个问题时,提供的解决方案是创建一个只接受字符指针的“持有人”类:

template< typename char_t >
class String
{
    struct holder_t
    {
        const char_t* s;
        holder_t( const char_t* s ) : s(s) {}
        holder_t( char_t* s ) : s(s) {}
    };
public:

    // Construct from string literal
    template< size_t S >
    String( const char_t (&str)[S] )
    {
        std::cout << "String Literal: " << str;
    }

    // Construct from char pointer
    String( holder_t h )
    {
        std::cout << "Char Pointer: " << h.s;
    }
};

最重要的想法是,您永远不必显式创建此类的实例,它应该通过隐式转换来实现:

void StringFoo( String<char> s )
{
}

但是这会导致 char 指针的编译错误,为什么隐式转换不起作用?

int main()
{
    // Works!
    StringFoo( "literal" );

    // error C2664: 'StringFoo' : cannot convert parameter 1 from 'const char *' to 'String<char_t>'
    // with [ char_t=char ]
    // No constructor could take the source type, or constructor overload resolution was ambiguous
    StringFoo( (const char*)"const char ptr" );

    // Works!
    StringFoo( String<char>((const char*)"const char ptr") );

    // error C2664: 'StringFoo' : cannot convert parameter 1 from 'char *' to 'String<char_t>'
    // with [ char_t=char ]
    // No constructor could take the source type, or constructor overload resolution was ambiguous
    StringFoo( (char*)"char ptr" );

    // Works!
    StringFoo( String<char>((char*)"const char ptr") );

    return 0;
}

这只是一个简单的毫无意义的例子;在我的真实代码中,我创建了一个保存字符串哈希的类。

如果传递的是字符串字面量,则应在编译时生成哈希值,如果传递的是字符指针,则应在运行时计算。

然而,这对于只传递字符串的用户来说应该是完全透明的,散列是自动完成的。

【问题讨论】:

  • 指针不是数组!
  • 第二个构造函数接受 holder_t 参数,该参数可以从 char 指针隐式构造。如果我显式创建实例,这很好用,我只是希望它隐式发生。
  • @sliser 字符串文字是一个数组。
  • @sliser:有人说或暗示它在哪里?

标签: c++


【解决方案1】:

代码不能使用指针的原因是它需要两个版本(char const*holderholderString。但是,隐式转换最多只能进行一次转换。

出于您所描述的目的,我认为您可以合理地区分 char const(&amp;)[N]char const*:因为无论如何您总是想计算一个哈希值,并尽可能将其设为 constexpr,使采用char const(&amp;)[N] 的版本应该可以解决问题。

【讨论】:

  • 感谢您提供使用 constexpr 的解决方法,但是目前我坚持使用不支持它的 vs 2012。有没有可能的方法让它在没有 constexpr 的情况下工作?如果没有,那么我想我会快速升级到 vs 2013...
  • 实际上我只是试图摆脱 holder_t 并且它似乎有效,我非常专注,因为我在某处读到你需要这个技巧来区分字符串文字和字符指针(字符串文字总是而是选择 char 指针重载),否则我不认为要尝试它。
  • “哈希应该在编译时生成”“让它在没有 constexpr 的情况下工作”这两者似乎不可能一起使用。
  • 你确定它是在编译时计算的吗?怎么样?
  • @n.m.是的,我使用 IDA pro 进行检查,但您可以在可执行文件上运行 strings 命令,然后查看您正在散列的字符串不存在。如果没有 __forceinline,msvc 将创建一个函数,该函数将在运行时计算哈希……任何强制循环展开的尝试都失败了,__forceinline + 手动展开的循环有效。不过,一旦我升级到 vs 2013,将替换为 constexpr。
【解决方案2】:

要从字符串文字到 String 需要两次用户定义的转换 - 一次到 holder_t,另一次到 String。但是重载决议只允许您对每个参数进行一次这样的转换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-15
    • 2015-02-22
    • 1970-01-01
    • 1970-01-01
    • 2012-03-10
    • 2015-05-19
    • 1970-01-01
    • 2015-01-02
    相关资源
    最近更新 更多