有没有理由字符串文字不能有外部链接?

时间:2017-06-21 18:54:31

标签: c++ string

想要具有外部链接的字符串文字背后的主要动机是to use string literals as non-type template parameters

我想象一个带有外部链接的字符串文字,其定义类似于

  

前缀中带有e的 string-literal 是带有外部链接的 string-literal

template<auto&> struct S{};
void bar()
{
    S<e"foo"> s;
}
     

将具有与

等效的行为
template<auto&> struct S{};
constexpr char __foo[] = "foo";
void bar
{
    S<__foo> s;
}

有没有理由没有外部链接字符串文字? 以某种方式添加另一个前缀(如e"Lorem Ipsum")来使字符串文字具有外部链接有害吗?

注意:已经可以实现外部链接字符串,但这是一种糟糕的做事方式。

#include<boost/metaparse/v1/string.hpp>

template<typename>
struct hack;

template<char... Cs>
struct hack<boost::metaparse::v1::string<Cs...>>
{
    static constexpr char arr[] = {Cs..., '\0'};
};

#define E(str) hack<BOOST_METAPARSE_STRING(str)>::arr

template<auto&> struct S{};
S<E("I'm an external linkage string")> s;  // compiles

Boost使用python脚本生成BOOST_METAPARSE_STRING的实现,这很糟糕。

3 个答案:

答案 0 :(得分:5)

由于P0732 class types in non-type template parameters,问题即将在C ++ 20中变得毫无意义。

非类型模板参数是基本类型和类类型之间不对称的最后痕迹。它不是通过选择而是必然的:不清楚链接器应该如何处理它们。

链接器需要能够区分两个模板类,为了做到这一点,它需要回答两个对象ab是否相等。对于基本类型来说这是微不足道的,但对于使用C ++ 20之前可用工具的类类型无法解决。

P0515 consistent comparison给出了确定两个类类型对象是否相等的机制,只要它们具有平凡的operator<=>,它具有成员比较的语义。

如果P0732通过,您就可以写

template<size_t N>
struct fixed_string
{
    constexpr fixed_string(const char (&str)[N]) { std::copy(str, str + N, data); }
    auto operator<=>(const fixed_string&, const fixed_string&) = default;
    char data[N];
};

template<size_t N>
fixed_string(const char(&)[N]) -> fixed_string<N>;

template<fixed_string> struct S {};
S<"foo"> s;

另请参阅有利于进入C ++ 20的thoughts on the text formatting library

答案 1 :(得分:2)

只能使用constexpr函数解析字符串。 这是一个非常简单的例子:

constexpr int placeholder_count(const char* s, size_t i = 0, int result = 0)
{
    return s[i] == 0
        ? result
        : (s[i] == '%')
        ? placeholder_count(s, i + 1, result + 1)
        : placeholder_count(s, i + 1, result);
}

int main()
{
  static_assert(placeholder_count("foo %s bar %d") == 2, "");
  return 0;
}

https://wandbox.org/permlink/TwN0UALpp0e6qfqr

使用它可以实现很多实际的东西,特别是如果允许使用C ++ 14,那么就需要更少的递归。

对于更高级的用例,签出metaparse: http://www.boost.org/doc/libs/1_64_0/doc/html/metaparse.html

答案 2 :(得分:1)

  

§3.5计划和联系[basic.link]

     
      
  1. 如果名称可能表示相同的对象,引用,函数,类型,模板,命名空间或值,则表示链接   由另一个范围内的声明引入的名称
  2.   

如评论中所述,只有名称具有链接。字符串文字不是名称。

  

§2.13.3字符串文字[lex.string]

     
      
  1. 评估字符串文字会导致字符串文字对象具有静态存储持续时间,从给定字符初始化为   如上所述。 是否所有字符串文字都是不同的(即,   存储在非重叠对象中)以及是否连续   对字符串文字的评估产生相同或不同的对象   未指明
  2.   

所以实际问题是具有相同值的不同字符串文字可以存储在不同的对象中。更重要的是,对同一文字的连续评估可以产生不同的对象。