Using boost::iostreams::mapped_file_source with wide character strings

不打扰是莪最后的温柔 提交于 2019-12-11 00:54:59

问题


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.


回答1:


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;



回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/6673938/using-boostiostreamsmapped-file-source-with-wide-character-strings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!