Compilation issue with boost range copy of filesystem path - boost

The following code fails to compile with 1.58 while it was compiling with 1.46. I guess it's a type conversion issue, but I can't make it right.
my code
#include <boost/filesystem.hpp>
#include <boost/range.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <vector>
using namespace boost;
using namespace filesystem;
using namespace adaptors;
int main(int argc, char ** argv)
{
recursive_directory_iterator beg = recursive_directory_iterator(".");
recursive_directory_iterator end = recursive_directory_iterator();
iterator_range<recursive_directory_iterator> files =
make_iterator_range(beg, end);
std::function<bool (path const & path)> fileFilter =
[](path const & path) -> bool {
return is_regular_file(path);
};
std::vector<path> paths;
copy(files | filtered(fileFilter), std::back_inserter(paths));
// works:
//copy(files, std::back_inserter(paths));
// also works:
//for(recursive_directory_iterator it = beg; it != end; ++it){
// if(fileFilter(*it)){
// paths.push_back(*it);
// }
//}
}
Error message (VS2010)
Error 1 error C2664:
'boost::filesystem::recursive_directory_iterator::recursive_directory_iterator(const
boost::filesystem::path
&,boost::filesystem::symlink_option::enum_type)' : cannot convert
parameter 1 from
'boost::iterators::detail::postfix_increment_proxy' to
'const boost::filesystem::path
&' [...]\boost\1.58.0_32\include\boost-1_58\boost\range\concepts.hpp 201 1 [...]
Can anyone help ?
Edit
Filed as https://svn.boost.org/trac/boost/ticket/11228.

This seems to be a bug introduced somewhere since Boost 1.55. Using boost 1.55 this compiles ok.
It could be this bug: https://svn.boost.org/trac/boost/ticket/10989
boost_1_57_0/boost/concept_check.hpp|210 col 13| error: conversion from ‘boost::iterators::single_pass_traversal_tag’ to non-scalar type ‘boost::iterators::forward_traversal_tag’ requested
The filtered adaptor requires the input to be forward_traversal tag. But recursive_directory_iterator only promises single_pass_traversal tag:
BOOST_RANGE_CONCEPT_ASSERT((
Convertible<
BOOST_DEDUCED_TYPENAME ForwardIteratorConcept::traversal_category,
forward_traversal_tag
>));
WORKAROUND
You can disable concept checks for now: -DBOOST_RANGE_ENABLE_CONCEPT_ASSERT=0:
Live On Coliru
#include <boost/filesystem.hpp>
#include <boost/range.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <vector>
#include <iostream>
namespace fs = boost::filesystem;
using namespace boost::adaptors;
int main() {
fs::recursive_directory_iterator beg("."), end;
auto fileFilter = [](fs::path const & path) { return is_regular_file(path); };
std::vector<fs::path> paths;
copy(boost::make_iterator_range(beg, end) | filtered(fileFilter), std::back_inserter(paths));
for(auto& p : paths)
std::cout << p << "\n";
}
Prints
"./main.cpp"
"./a.out"

Related

boost filesystem making long path under windows using \\?\

it is so simple but i can not make it work and i do not know why??
i just want to make directory with long path.
i add \\\\?\\ to E:\\... to make it as win api says .
but in vain.....nothing but error.
i tried \\?\ and \?\ with no success.
this is the code :
// boost_create_directory.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <fstream>
#include <string>
#include <time.h>
#include <stdio.h>
#include <ctime>
#include <iostream>
#include <map> //Needed to use the std::map class.
//#include "symbols_array2.h"
//#include "functions.h"
#include <boost/filesystem.hpp>
//#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
////#include <filesystem>
////namespace fs = std::filesystem;
//#define DOWNLOAD_ALL true
int main()
{
using namespace std;
using namespace boost::filesystem;
//string localpath, binlocalfile, localfile;
string localpath = "\\\\?\\E:\\instruments\\symbol\\year\\month\\day\\";
//boost::filesystem::path abs_localpath;
////string localpath = "E:\\instruments\\symbol\\year\\month\\day\\";
boost::filesystem::path abs_localpath(localpath) ;
////string localpath = "\\\\?\\E:\\instruments\\symbol\\year\\month\\day\\";
////boost::filesystem::path abs_localpath("\\\\?\\E:\\instruments\\symbol\\year\\month\\day\\");
////string localpath = "E:/i/";
////boost::filesystem::path abs_localpath("\\?\E:\instruments\symbol\year\month\day\\");
////boost::filesystem::path path_argument(localpath);
////boost::filesystem::path path_native(path_argument.make_preferred());
////boost::filesystem::path abs_localpath(absolute(path_native));
//binlocalfile = localpath + "\\hourh_ticks.bin";
//localfile = localpath + "\\hourh_ticks.bi5";
//abs_localpath = boost::filesystem::absolute(localpath.c_str());
//abs_localpath = localpath;
//if (!boost::filesystem::exists(abs_localpath))
//{
//boost::filesystem::path abs_localpath;
//cout << current_path().string() << endl;
//cout << abs_localpath << endl;
//boost::filesystem::create_directory(abs_localpath);
for (int z = 0; z < 10; z++)
{
if (boost::filesystem::create_directory(abs_localpath)) {
std::cout << "Success making new directory" << "\n";
//boost::filesystem::permissions(abs_localpath, perms_mask);
}
//localpath = localpath + "\\instruments\\symbol\\year\\month\\day";
abs_localpath / "instruments\\symbol\\year\\month\\day\\";
////abs_localpath /= "\instruments\symbol\year\month\day\";
}
//mkdir($localpath, 0777, true);
//}
boost::filesystem::path path("\\?\\E:\\MyStuff\\");
boost::filesystem::create_directory(path);
return 0;
}
i hope to find answer here.thanks in advance.
it was my fault .the create_directory function make single directory if path is already created and return with error if path is missing,So i needed create_directories the plural version make all missing elements of path and voila.
i wish they change these names to create_single_directory or create_target_directory and change the plural to create_path_directories

boost locale bad cast exception

The following simple code, compiled with -lboost_locale generates a bad cast exception. It is the same code in the boost tutorial itself. Any help?
#include <boost/locale.hpp>
#include <iostream>
int main()
{
using namespace boost::locale;
date_time now;
std::cout<<as::date<<now<<std::endl;
}
You need to imbue (global) locales:
Live On Coliru
#include <boost/locale.hpp>
#include <iostream>
int main() {
using namespace boost::locale;
boost::locale::generator gen;
std::locale loc = gen.generate(""); // or "C", "en_US.UTF-8" etc.
std::locale::global(loc);
std::cout.imbue(loc);
date_time_period_set things;
date_time now;
std::cout << as::date << now << std::endl;
}
Prints, e.g. on coliru:
09/17/15

initializer_lists of streams (C++11)

I'm trying to pass variable number of ofstreams over to a function that accepts an initializer_list but doesn't seem to work and throws all possible errors from the initializer_list structure and about how my function is with an array of ofstreams cannot be matched to any defined function.
Is it actually possible to pass a reference of ofstreams over in an initializer_list?
test.cpp
#include "extension.h"
ofstream outputFile, outputFile2;
int main(void) {
outputFile.open(("data_1.txt");
outputFile2.open("data_2.txt");
writeSomething({outputFile, outputFile2});
outputFile.close();
outputFile2.close();
}
extension.h
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <string.h>
#include <initializer_list>
using namespace std;
void writeSomething(initializer_list<ofstream&> args);
extension.cpp
#include "extension.h"
void writeSomething(initializer_list<ofstream&> args) {
for (auto f : args ) {
f << "hello" << endl;
}
}
clang 3.4 (trunk 194324) produces a pretty clear error message:
initializer_list:54:23: error: 'iterator' declared as a pointer to a
reference of type
'std::basic_ofstream<char> &'
typedef const _E* iterator;
So no, it is not possible. See also Error: forming pointer to reference type 'const std::pair&'… I can't understand this error.
(gcc 4.7.2 and 4.8.1 crashes on this code due to some internal compiler error. I have submitted a bugreport.)
What you could do instead is to pass a pointer instead of a reference, something like this:
#include <fstream>
#include <initializer_list>
using namespace std;
void writeSomething(initializer_list<ofstream*> args) {
for (auto f : args )
*f << "hello" << endl;
}
int main() {
ofstream outputFile("data_1.txt");
ofstream outputFile2("data_2.txt");
writeSomething({&outputFile, &outputFile2});
}
However, I would much rather use a std::vector instead. Using an initializer list for this purpose is very strange and confusing for me.

Storing a boost::spirit::qi::rule in a std::list

I have read the other thread about copy or reference semantics for boost::spirt::qi::rule. I am using Boost 1.42.
using boost::spirit::qi::phrase_parse;
typedef boost::spirit::qi::rule < std::string::const_iterator, boost::spirit::ascii::space_type > rule_type;
std::list < rule_type > ruleList;
std::string const s("abcdef");
std::string::const_iterator iter = s.begin(), end = s.end();
std::cout << typeid(char_).name() << std::endl;
ruleList.push_back(char_);
ruleList.push_back(*ruleList.back());
assert(phrase_parse(iter, s.end(), ruleList.back(), boost::spirit::ascii::space));
assert(iter == s.end());
This fails with...
Assertion `phrase_parse(iter, s.end(), ruleList.back(), traits::space())' failed.
Aborted (core dumped)
Is there a way to store rules in a STL list or deque? (References don't die until removed).
With Boost V1.45, this (essentially your code from above) works without problems (MSVC2010, g++ 4.5.1):
#include <list>
#include <string>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
using namespace boost::spirit;
int main()
{
typedef qi::rule<std::string::const_iterator, ascii::space_type> rule_type;
std::list<rule_type> ruleList;
std::string const s("abcdef");
std::string::const_iterator iter = s.begin(), end = s.end();
std::cout << typeid(qi::char_).name() << std::endl;
ruleList.push_back(qi::char_);
ruleList.push_back(*ruleList.back());
assert(qi::phrase_parse(iter, s.end(), ruleList.back(), ascii::space));
assert(iter == s.end());
return 0;
}
Therefore, I assume it's a bug in the version of Spirit you're using.
I could not get your example to compile. Aside from not using the correct types from ...::qi, you added a () to the trait::space type.
This works w/o problem for me (boost 1.44)
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <vector>
#include <cassert>
using boost::spirit::qi::phrase_parse;
typedef boost::spirit::qi::rule < std::string::const_iterator, boost::spirit::qi::space_type > rule_type;
int main() {
std::list < rule_type > ruleList;
std::string const s("abcdef");
std::string::const_iterator iter = s.begin(), end = s.end();
ruleList.push_back(*boost::spirit::qi::char_);
assert(phrase_parse(iter, s.end(), ruleList.back(), boost::spirit::qi::space));
assert(iter == s.end());
}
~>g++ test.cpp && ./a.out
~>
please note I use qi::space_type and `qi::space instead of the ascii namespace. I have no idea what/where the trait namespace is.

boost.log auto_flush files are not stored when app is crashed

Recently I started to play with boost.log, and bumped into an issue that if an unhanded exception is thrown no log messages are written to the log file. I am using rolling text files and auto-flash option is set on.
Here is the modified source from the samples:
#include <stdexcept>
#include <string>
#include <iostream>
#include <fstream>
#include <functional>
#include <boost/ref.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <boost/log/common.hpp>
#include <boost/log/filters.hpp>
#include <boost/log/formatters.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/utility/empty_deleter.hpp>
#include <boost/log/utility/record_ordering.hpp>
namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace fmt = boost::log::formatters;
namespace keywords = boost::log::keywords;
using boost::shared_ptr;
using namespace boost::gregorian;
enum
{
LOG_RECORDS_TO_WRITE = 100,
LOG_RECORDS_TO_WRITE_BEFORE_EXCEPTION = 10,
THREAD_COUNT = 10
};
BOOST_LOG_DECLARE_GLOBAL_LOGGER(test_lg, src::logger_mt)
//! This function is executed in multiple threads
void thread_fun(boost::barrier& bar)
{
// Wait until all threads are created
bar.wait();
// Here we go. First, identify the thread.
BOOST_LOG_SCOPED_THREAD_TAG("ThreadID", boost::thread::id, boost::this_thread::get_id());
// Now, do some logging
for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
{
BOOST_LOG(get_test_lg()) << "Log record " << i;
if(i > LOG_RECORDS_TO_WRITE_BEFORE_EXCEPTION)
{
BOOST_THROW_EXCEPTION(std::exception("unhandled exception"));
}
}
}
int main(int argc, char* argv[])
{
try
{
typedef sinks::synchronous_sink< sinks::text_file_backend > file_sink;
shared_ptr< file_sink > sink(new file_sink(
keywords::file_name = L"%Y%m%d_%H%M%S_%5N.log", // file name pattern
keywords::rotation_size = 10 * 1024 * 1024, // rotation size, in characters
keywords::auto_flush = true // make each log record flushed to the file
));
// Set up where the rotated files will be stored
sink->locked_backend()->set_file_collector(sinks::file::make_collector(
keywords::target = "log" // where to store rotated files
));
// Upon restart, scan the target directory for files matching the file_name pattern
sink->locked_backend()->scan_for_files();
sink->locked_backend()->set_formatter(
fmt::format("%1%: [%2%] [%3%] - %4%")
% fmt::attr< unsigned int >("Line #")
% fmt::date_time< boost::posix_time::ptime >("TimeStamp")
% fmt::attr< boost::thread::id >("ThreadID")
% fmt::message()
);
// Add it to the core
logging::core::get()->add_sink(sink);
// Add some attributes too
shared_ptr< logging::attribute > attr(new attrs::local_clock);
logging::core::get()->add_global_attribute("TimeStamp", attr);
attr.reset(new attrs::counter< unsigned int >);
logging::core::get()->add_global_attribute("Line #", attr);
// Create logging threads
boost::barrier bar(THREAD_COUNT);
boost::thread_group threads;
for (unsigned int i = 0; i < THREAD_COUNT; ++i)
threads.create_thread(boost::bind(&thread_fun, boost::ref(bar)));
// Wait until all action ends
threads.join_all();
return 0;
}
catch (std::exception& e)
{
std::cout << "FAILURE: " << e.what() << std::endl;
return 1;
}
}
Source is compiled under Visual Studio 2008. boost.log compiled for boost 1.40.
Any help is highly appreciated.
Check to see if the log file is in the current working directory of the process, rather than the specified file collector target directory ("log" in your sample code). Additionally, you will probably want to specify a directory for the sink "file_name" pattern.
As "JQ" notes, don't expect to see any logging post-exception.

Resources