Using boost::iostreams::mapped_file_source with wi

2019-07-22 03:12发布

If I instantiate a mapped_file_source (boost 1.46.1 ) with a narrow character string as in the following I don't have a problem:

boost::iostreams::mapped_file_source m_file_( "testfile.txt" );

However if I try to use a wide string:

boost::iostreams::mapped_file_source m_file_( L"testfile.txt" );

I get the following compiler error in VC2010 SP1:

P:\libs\boost_1_46_1\boost/iostreams/device/mapped_file.hpp(128): error C2248: 'boost::iostreams::detail::path::path' : cannot access private member declared in class 'boost::iostreams::detail::path'
          P:\libs\boost_1_46_1\boost/iostreams/detail/path.hpp(111) : see declaration of 'boost::iostreams::detail::path::path'>
          P:\libs\boost_1_46_1\boost/iostreams/detail/path.hpp(37) : see declaration of 'boost::iostreams::detail::path'

If I instead try to pass the constructor a boost::filesystem::path I get the following error:

P:\libs\boost_1_46_1\boost/iostreams/device/mapped_file.hpp(128): error C2664: 'boost::iostreams::detail::path::path(const std::string &)' : cannot convert parameter 1 from 'const boost::filesystem3::path' to 'const std::string &'
         Reason: cannot convert from 'const boost::filesystem3::path' to 'const std::string'

I feel like I'm missing something obvious, but I'm just running around in circles trying to figure out what the compiler is trying to tell me, but I'm just getting lost. That palm to forehead moment is just not happening.. What is it that I am doing incorrectly?

The constructor defined in mapped_file.hpp looks like the following:

// Constructor taking a parameters object
template<typename Path>
explicit mapped_file_source(const basic_mapped_file_params<Path>& p);

The basic_mapped_file_params class constructors look like this:

// Construction from a Path
explicit basic_mapped_file_params(const Path& p) : path(p) { }

// Construction from a path of a different type
template<typename PathT>
explicit basic_mapped_file_params(const PathT& p) : path(p) { }

Where the template class is defined as:

// This template allows Boost.Filesystem paths to be specified when creating or
// reopening a memory mapped file, without creating a dependence on
// Boost.Filesystem. Possible values of Path include std::string,
// boost::filesystem::path, boost::filesystem::wpath, 
// and boost::iostreams::detail::path (used to store either a std::string or a
// std::wstring).
template<typename Path>
struct basic_mapped_file_params 
    : detail::mapped_file_params_base 
{

There is some additional help in the header that says:

// For wide paths, instantiate basic_mapped_file_params 
// with boost::filesystem::wpath

If I take this approach with:

boost::iostreams::basic_mapped_file_params<boost::filesystem::wpath> _tmp(L"test.txt");
boost::iostreams::mapped_file_source m_file_( _tmp );

I get the same C2664 error mentioned above..

I know the compiler is telling me what the problem is, but looking at the header source and the comments leads me to believe that what I'm trying to accomplish is supported, it's just my approach that is incorrect. Am I misinterpreting what the header file is telling me? I know there is probably a good lesson about template instantiation and explicit/implicit conversion in here somewhere.

Interestingly enough, upgrading my boost install to 1.47.0 seems to cleared up C2664 error but I'm still getting the C2248 error about access to the private member.

3条回答
一夜七次
2楼-- · 2019-07-22 03:59

With boost 1.48 I can do something like this.

#include <boost/filesystem.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <iostream>

int main()
{ 
  boost::filesystem::path p(L"b.cpp");
  boost::iostreams::mapped_file file(p); // or mapped_file_source
  std::cout << file.data() << std::endl;
}

or you can do this with mapped_file_params(used create new file)

boost::filesystem::path p(L"aa");
basic_mapped_file_params<boost::filesystem::path> param; // template param
param.path = p;
param.new_file_size = 1024;
查看更多
走好不送
3楼-- · 2019-07-22 04:02

It looks like the documentation for mapped_file is pretty old and does not reflect what is in the header or in the header comments. In order to instantiate a boost::iostreams:mapped_file_source object with a wide character string you need to explicity pass in the boost::iostreams::detail::path like this:

boost::iostreams::mapped_file_source m_file_( boost::iostreams::detail::path(boost::filesystem::path(L"testfile.txt")) );

I was able to get this to compile by stepping thought the error messages and determining how the template classes were being instantiated and finally saw that boost::iostreams::detail::path had a private constructor that took a &std::wstring as a parameter which is where the code was failing to compile.

查看更多
迷人小祖宗
4楼-- · 2019-07-22 04:10

It's telling you that boost::iostreams::mapped_file_source's constructor does not take a wchar_t*, nor does it take a boost::filesystem::path. It only takes std::string, or types convertible to std::string. Or, to put it another way, you can't use UTF-16 paths with this object.

查看更多
登录 后发表回答