Is there a reason why string literals cannot be externally linked?

The main motivation behind wanting an externally linked string literal is to use string literals as parameters for a non-python template .

I would guess that an externally linked string literal has a definition like

A string literal prefixed with e is an externally linked string literal.

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

      

will have behavior equivalent to

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

      

Is there a reason not to have external link string literals? Somehow adds another prefix (like e"Lorem Ipsum"

) to make the string literal harmful to external links?

Note: It is already possible to get the outer binding string, but this is a terrible way to do things.

#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 uses a python script to generate the implementation BOOST_METAPARSE_STRING

, which is terrible.

+3


source to share


3 answers


The question of becoming controversial in C ++ 20 due to P0732 Class Types in non-python template parameters .

The non-python type template parameters are the last remnants of an asymmetry between basic types and class types. This was not a choice, but out of necessity: it is not clear how the linkers should work with them.

Linkers must be able to distinguish between the two classes of templates, and for this it is necessary to answer whether the two objects are equal a

and b

. This was trivial for basic types, but not resolvable for class types with tools available before C ++ 20.

P0515 consensus comparison provided a mechanism for determining whether two objects of class type are equal, provided that they have trivial operator<=>

, which has method comparison semantics.



If P0732 passes, you should be able to write

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;

      

See also thoughts on text formatting library who would also prefer to migrate to C ++ 20.

+4


source


It is possible to parse strings using only constexpr functions. Here's a very simple example:

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



You can do a lot of practical things using this, especially if C ++ 14 is allowed then less recursion is required.

For more advanced use cases, checkout metaphors: http://www.boost.org/doc/libs/1_64_0/doc/html/metaparse.html

+2


source


ยง 3.5. Program and communication [basic.link]

  1. A name is said to have a relationship when it can denote the same object, reference, function, type, template, namespace, or value as a name entered by a declaration in a different scope.

As mentioned in the comments, only names are anchored. String literals are not names.

ยง 2.13.5 String literals [lex.string]

  1. Evaluating a string literal results in a string literal object with static storage time initialized from the given characters as above. Whether all string literals are (that is, stored in objects with non-overlapping objects) and string literal evaluations yield the same or a different object is unspecified .

So the actual problem is that different string literals with equal value can be stored in different objects. Moreover, consecutive evaluations of the same literal can yield different objects.

+1


source







All Articles