【问题标题】:Tell a const char array that does not ends with '\0' apart from a C-style string in compile time在编译时告诉一个不以 '\0' 结尾的 const char 数组,而不是 C 样式的字符串
【发布时间】:2020-07-14 02:51:05
【问题描述】:

除了 C 风格的字符串之外,是否可以在编译时告诉一个不以 '\0' 结尾的 const char 数组?

假设我想为一个类编写两个构造函数。

一个构造函数从 C 风格的字符串构造,以 '\0' 结尾。

另一个具有不同行为的构造函数从不以 '\0' 结尾的 const char 数组构造。

作为一个最小的例子,考虑

#include <cstddef>
#include <iostream>

struct Foo
{
    Foo(const char *)
    {
        std::cout << "a C-style string" << std::endl;
    }

    // Question: How to modify Foo so that a const char array that does not
    //           ends with '\0' will go to a different constructor?
    template<size_t N>
    Foo(const char (&)[N])
    {
        std::cout << "a const char array "
                     "that does not ends with '\\0'" << std::endl;
    }
};

int main()
{
    Foo("a C-style string");          // print "a C-style string"

    const char a[3] {'a', 'b', 'c'};
    Foo foo(a);                       // print "a C-style string" - can it change?

    return 0;
}

使用g++ -std=c++17编译。

问题:有什么办法可以做到吗?

也许我可以应用 SFINAE 技术,但我还没有弄清楚如何去做。

注意:目前 StackOverflow 上有几个类似但不相同的问题。我没有找到直接解决我的问题的问题。

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    不,那样是不可能的。重载决议时,非模板函数更可取。 C++ template functions overload resolution

    非模板函数是一等公民。

    Why does overload of template and non-template function with the “same signature” call the non-template function?

    当模板函数和非模板函数都可用于解析函数调用时,选择非模板函数。

    可能的解决方法:

    struct Foo
    {
        void Cstr(const char *)
        {
            std::cout << "a C-style string" << std::endl;
        }
    
        template<size_t N>
        Foo(const char (&s)[N])
        {
            if (N > 0 && !s[N - 1])
                Cstr(s);
            else
                std::cout << "a const char array "
                             "that does not ends with '\\0'" << std::endl;
        }
    };
    

    【讨论】:

      【解决方案2】:

      有趣的是,如果在数组声明中删除const,它会与数组构造函数一起使用

      #include <cstddef>
      #include <iostream>
      
      struct Foo
      {
          Foo(const char *)
          {
              std::cout << "a C-style string" << std::endl;
          }
      
          template<size_t N>
          Foo(const char (&)[N])
          {
              std::cout << "a const char array "
                           "that does not ends with '\0'" << std::endl;
          }
      };
      
      int main()
      {
          Foo("a C-style string");
      
          // const char a[3] {'a', 'b', 'c'};
          char a[3] {'a', 'b', 'c'};
          Foo foo(a);
      
          return 0;
      }
      

      【讨论】:

      • 感谢您的观察。没错,但这会改变用户代码,因此不是真正的解决方案。
      • 是的,我只是弹出观察,看看是否有人可以解释,这可能会导致正确的解决方案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-07
      • 2016-06-19
      相关资源
      最近更新 更多