boostorg/utility

boost::basic_string_view should have a trivial constructor from std::basic_string_view

Opened this issue · 11 comments

I am trying to use beast which makes heavy use of boost::string_view in code that already makes heavy use of std::string_view. It is awfully easy to make a constexp constructor that trivially converts a std::string_view to a boost::string_view. I added one myself but I would appreciate it if you guys would go ahead and add it in too.

      BOOST_CONSTEXPR basic_string_view(const std::basic_string_view<charT, traits>& str) BOOST_NOEXCEPT
      : ptr_(str.data()), len_(str.size()) {}
mclow commented

This has come up before, and would require a dependency between boost::string_view and std::string_view (which implies C++17 only).

Better for you (who already have both included) to define a conversion function. Something like:

template <typename charT, typename Traits>
BOOST_CONSTEXPR operator boost::basic_string_view<charT, Traits> 
    (const std::basic_string_view<charT, Traits>& str) BOOST_NOEXCEPT
    { return boost::basic_string_view<charT, Traits>(str.data()), str.size()); }

@mclow your example will not compile. C++ does not support out of class operators - they must me members of the class:
http://en.cppreference.com/w/cpp/language/cast_operator
In my opinion it would be much better for Boost to just alias std::basic_string_view as boost::basic_string_view if it's available.

boost::basic_string_view is not equivalent to std::basic_string_view.

I was thinking, if c++17 is enabled, boost::string_view may inherit from std::string_view and implement the additional functions in terms of the public interface (data, size, traits_type, etc). The inherited class won't add any new data members, so slicing would be same as copy.

It can be done with macros or with template trickery.

#if __cplusplus >= 2017...
class basic_string_view: public std::basic_string_view {
//...
#else
class basic_string_view {
//...
#endif
mclow commented

I'd rather not require a dependency on std::string_view in boost::string_view.

Why is the dependency a problem (when C++17 and __has_include(<string_view>))?

This issue is relevant to me in the last 4 applications I have written.
C++17 and 20 are now the standard of choice when writing applications and servers. std::string_view is ubiquitous, and I use many boost libraries which use boost's version (beast, boost.json etc).

Annoyingly, boost.asio uses std::string_view. Regular conversions are inevitable. This adds noise to the source code at the call sites of functions involving string_view - the exact opposite of its intent.

It means that every project needs a file like this:

#pragma once
#include <boost/json.hpp>
#include <string_view>

namespace my_awesome_project::config::json
{
    using namespace boost::json;

    inline auto convert(std::string_view sv)
    {
        return string_view(sv.data(), sv.size());
    }

    inline auto convert(json::string_view sv) { return sv; }
}   // namespace my_awesome_project::config::json

The automatic conversion when c++17 or higher is detected would be most welcome.

Having a default constructor from std::basic_string_view would be really useful for the MySQL client library I am writing and want to propose for Boost.

+1 for this one. There are good compile time checks about C++ version so std::string_view can be a dependency only in C++17 mode.

@mclow please reconsider

I'd rather not require a dependency on std::string_view in boost::string_view.

This seems rather insignificant given that you already have a dependency on <string>.

That aside, perhaps this issue could be solved by adding a range-based constructor, just as std::string_view gets in c++23?

That aside, perhaps this issue could be solved by adding a range-based constructor, just as std::string_view gets in c++23?

That constructor is causing problems in real code bases and IMO is a mistake. See P2516 for example. It is causing problems in Boost.Filesystem as well, as I have to special-case std::string_view to avoid overload ambiguities in path implementation. I'd be opposed to adding it to boost::string_view.

Actually, I was told that P2499 was merged into the standard draft, making the constructor explicit. So this constructor won't cause as much trouble but also won't help with conversion from std::string_view to boost::string_view.