nlohmann json cannot assign std::string - c++

I am puzzled that this very basic code does not compile on windows with msvc 16.8.3 and c++17 (compiles fine with gcc)
#include "json.hpp"
#include <string>
int main() {
nlohmann::json j;
j["mykey"] = std::string("my value");
return 0;
}
It fails immediately with:
no operator "=" matches these operands -- operand types are: nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double, std::allocator, nlohmann::adl_serializer, std::vector<uint8_t, std::allocator<uint8_t>>> = std::stringC/C++(349)
json.hpp(18662,17): message : could be 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer,std::vector<uint8_t,std::allocator<uint8_t>>> &nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer,std::vector<uint8_t,std::allocator<uint8_t>>>::operator =(nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer,std::vector<uint8_t,std::allocator<uint8_t>>>) noexcept'
message : while trying to match the argument list '(nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer,std::vector<uint8_t,std::allocator<uint8_t>>>, std::string)'
My CMakeLists.txt is super simple:
cmake_minimum_required(VERSION 3.5)
project(api LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(jsontest main.cpp json.hpp)

As far as I know you need to use json.parse() to create the string object.
j["mykey"] = nlohmann::json.parse("my value");
But it's been a while since I last used the library.

Related

CMake misinterpret types inside c++ program

Good day. Building program without using cmake
''' g++ -lpthread src/how2thread.cpp src/main.cpp -ggdb3 -std=c++17 -Wextra '''
produces no errors.
Although, using
'''
cmake . && make
'''
generates following build errors:
[ 25%] Building CXX object CMakeFiles/how2thread_lib.dir/src/how2thread.cpp.obj
D:/Scizzors/Dsktp/cpp/how2thread/src/how2thread.cpp: In member function 'how2thread::Request how2thread::Scheduler::get_request()':
D:/Scizzors/Dsktp/cpp/how2thread/src/how2thread.cpp:103:67: error: use of deleted function 'std::lock_guard<_Mutex>::lock_guard(const std::lock_guard<_Mutex>&) [with _Mutex = std::mutex]'
103 | auto m_lock = std::lock_guard<std::mutex>(data_arr_protect);
| ^
In file included from C:/msys64/mingw64/include/c++/12.1.0/mutex:43,
from D:/Scizzors/Dsktp/cpp/how2thread/src/how2thread.hpp:8,
from D:/Scizzors/Dsktp/cpp/how2thread/src/how2thread.cpp:4:
C:/msys64/mingw64/include/c++/12.1.0/bits/std_mutex.h:237:7: note: declared here
237 | lock_guard(const lock_guard&) = delete;
I specify in my header file, that data_arr_protect is std::mutex object
class Scheduler
{
// class for schedule slicers, processors and collecting data
public:
Scheduler(const std::vector<char>& data,
const std::string& mask); // construct and parse data
Request get_request(); // used to get another batch
void write_request(Request&&);
void write_finding(Finding&& find);
using Find_it = decltype(std::declval<std::vector<Finding>&>().cbegin());
Find_it cbegin();
Find_it cend();
const auto& get_slicing_status(){return is_slicing;} //
std::string mask;
#ifndef DEBUG_V
private:
#endif
const size_t slicer_num;
std::queue<Request> data_arr; // consider switching to deQ
std::mutex data_arr_protect;//for mt rw to vec // might be switching to semaphores
std::queue<Actor_processor> proc_instances_q;
std::queue<Actor_slicer> slicer_instances_q;
std::vector<Finding> result_arr;
std::mutex result_protect;//for mt write to vec
protected:
friend class Actor_slicer; // we need access from slicers to mutexes as they're pretty lowlvl
std::vector<std::mutex> char_segments_protect;
std::vector<size_t> finish_line_no;
std::atomic<size_t> is_slicing; // for break cond
};
My cmake file looks next
cmake_minimum_required(VERSION 3.10.0)
project(how2thread
VERSION 0.0.1
DESCRIPTION "simple mt parser app"
LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
file(GLOB_RECURSE src_files src/*.cpp)
add_library(how2thread_lib src/how2thread.cpp src/how2thread.hpp)
add_executable(how2thread src/main.cpp)
target_link_libraries(how2thread PRIVATE how2thread_lib)
target_link_libraries(how2thread PRIVATE Threads::Threads)
What can cause compiler's misinterpretation and how i must fix it?
I tried different linking options, as building my how2thread.cpp file with main.cpp file, although it didn't help. And I do not get errors about undefined class or something, so, I guess, header file being included by .cpp one
Nothing is being misinterpreted. The issue is the following line: (Which appears only in the error message, not the code you show. Please always provide a minimal reproducible example!)
auto m_lock = std::lock_guard<std::mutex>(data_arr_protect);
This is copy-initialization of m_lock from the initializer expression which before C++17 required the type to be move-constructible, which std::lock_guard is not. Direct-initialization with auto (e.g. auto m_lock(std::lock_guard<std::mutex>(data_arr_protect));) would also not work for the same reason.
To compile this line you need to use C++17 or later, but you are asking cmake to set C++14 with
set(CMAKE_CXX_STANDARD 14)
So change the 14 to 17.
Or if you require compatibility with C++14, you will have to avoid the auto initialization idiom for non-movable types:
std::lock_guard<std::mutex> m_lock(data_arr_protect);

C++ if initializer

cmake_minimum_required(VERSION 3.16)
project(competitive_programming)
set(CMAKE_CXX_STANDARD 17)
add_executable(competitive_programming main.cpp)
As you see, I'm using C++ 17, and I want to use if initializer to keep the code neat,
if (auto result = right.find(second); result != right.end()){
result->second--;
}
But the compiler does not work as is supposed to be,
The readout seems as follows:
error: expected ')' before ';' token
if (auto result = right.find(item); result == right.end()){error: expected ')' before ';' token
if (auto result = right.find(item); result == right.end()){
My compiler is so, I guess:
g++ (x86_64-posix-seh, Built by strawberryperl.com project) 8.3.0
Try adding:
set(CMAKE_CXX_STANDARD_REQUIRED ON)
to your CMakeLists.txt. It makes sure that you are compiling with C++17 and it is not decayed to previous versions of compiler.

Compiler does not recognize member initializer for std::vector

I want to initialize a std::vector to have a specific length.
in the .hpp file I use
#include <vector>
class foo
{
foo(){};
~foo(){};
std::vector<double> pressure (4,0); //vector 4 elements = 0
void readPressure()
{
pressure.at(0) = 1;
pressure.at(1) = 2;
pressure.at(2) = 3;
pressure.at(3) = 4;
}
...
};
But I get the error:
error: expected identifier before numeric constant
std::vector<double> pressure(4,0);
^
error: expected ',' or '...' before numeric constant
I read that this might be due to not using C++11 but I specify in my makefile
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
I am compiling on a raspberry 4, g++ version is 8.3
***edited the .hpp file
Default member initializer (since C++11) only supports brace and equal-sign initializer. E.g.
class foo
{
std::vector<double> pressure = std::vector<double>(4,0); //vector 4 elements = 0
...
};
BTW: We can't use braced-initializer as std::vector<double> pressure{4,0};, because it would initialize the vector containing 2 elements with value 4 and 0, which is not what you want.

AppleLLVM 9.1.0 with c++17 support? or was it a cmake/env issue?

I've been working on os X 10.13 with AppleLLVM 9.1.0(clang-902.0.39.1), and example as follow
#include <experimental/optional>
#include <iostream>
template<typename T>
class p {
public:
T value;
p(T& t):value(t){}
p(T const& t):value(t){}
~p() = default;
};
template <typename T1, typename T2>
constexpr auto operator+(p<T1> const &lhs, p<T2> const &rhs) noexcept {
return p<decltype(lhs.value + rhs.value)>(lhs.value + rhs.value);
}
int main(int, char* []) {
p<int> v1(20);
p<int> v2(10);
auto v3 = v1+v2;
std::cout << v3.value <<std::endl;
return 0;
}
compiled with
c++ -std=c++17 -o test test.cpp
it works perfect for I was just trying to use the new feature of return type deduction as referred in N3638 which proposed a written style as
template<typename T> auto f(T t);
However, when I was about to use it in my CMake(3.11.1) organized project with several flags show as follow:
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS "-Wall -fpermissive -Wno-unused-parameter -Werror")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -ggdb3")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -ggdb3 -DNDEBUG")
it failed to compile telling me "'auto' return without trailing return type; deduced return types are a C++14 extension".
and I've tried the next flag also getting the same result:
set(CMAKE_CXX_FLAGS "-std=c++17")
It mostly look alike a CMake problem failing at environment set, while I got confused about what CMake flags should I set to enable this new feature? Or was it a compiler-related issue?
Sry guys.
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
works absolutely fine.
The problem was caused by an old version dependency library which used "std::auto_ptr" deprecated in c++11 and removed in c++17 (however still compiles in c++11), hence the CMakeLists was dedicated to c++11 standard.
Problem solved.
And in my ubuntu env, the old version library was updated by apt-get.

Magick++ undefined reference to Magick::Image::Columns

Good day,
here is my code
#include <iostream>
#include <Magick++.h>
using namespace std;
using namespace Magick;
int main(int argc, char **argv) {
InitializeMagick(*argv);
Image image;
try {
image.read(argv[1]);
}
catch( Exception &error_ ) {
cout << "Caught exception: " << error_.what() << endl;
return 1;
}
int x = image.columns();
cout<<"your picture's width is "<< x << "px"<<endl;
return 0;
}
I use KDevelop(which uses CMake as builder),
when I try to compile the app, it throws me an error
main.cpp:25: undefined reference to `Magick::Image::columns() const'
Here's what my CMakeLists.txt contains.
cmake_minimum_required(VERSION 3.5)
project(hello)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(hello ${SOURCE_FILES})
add_definitions( -DMAGICKCORE_QUANTUM_DEPTH=16 )
add_definitions( -DMAGICKCORE_HDRI_ENABLE=0 )
find_package(ImageMagick COMPONENTS Magick++)
include_directories(${ImageMagick_INCLUDE_DIRS})
target_link_libraries(hello ${ImageMagick_LIBRARIES})
I figured out that there're often issues with undefined references when CMakeLists isn't written correctly, but I made it according to this About Magick++, how to write the CMakeLists?
where am I wrong? I can add any information needed.
UPD 1.
version of magick++,
8:6.8.9.9-7ubuntu5.7
system info:
Description: Linux Mint 18.1 Serena
UPD 2.
I just removed parenthesis and when tryed to compile with
size_t x = image.columns;
size_t y = image.rows;
KDevelop threw me
main.cpp:25:22: error: cannot convert ‘Magick::Image::columns’ from type ‘size_t (Magick::Image::)() const {aka long unsigned int (Magick::Image::)() const}’ to type ‘size_t {aka long unsigned int}’
even when
auto x = image.columns;
auto y = image.rows;
it throws
main.cpp:25:20: error: cannot convert ‘Magick::Image::columns’ from
type ‘size_t (Magick::Image::)() const {aka long unsigned int
(Magick::Image::)() const}’ to type ‘long unsigned int
(Magick::Image::*)() const’
what's happening?
P.S. hooray, this is my first question on stackoverflow! :-)
If you are able to compile your program without CMake using g++ main.cpp `Magick++-config --cxxflags --cppflags --ldflags --libs` (but for some reason cannot use ${ImageMagick_LIBRARIES} in CMake), then you can make use of Magick++-config in your CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(hello LANGUAGES CXX)
add_executable(hello main.cpp)
target_compile_features(hello PRIVATE cxx_std_11)
find_package(ImageMagick REQUIRED COMPONENTS Magick++)
target_compile_definitions(hello PRIVATE
MAGICKCORE_QUANTUM_DEPTH=16
MAGICKCORE_HDRI_ENABLE=0
)
target_include_directories(hello PRIVATE ${ImageMagick_INCLUDE_DIRS})
execute_process(COMMAND Magick++-config --ldflags
OUTPUT_VARIABLE ImageMagick_LINK_FLAGS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
target_link_libraries(hello PRIVATE ${ImageMagick_LINK_FLAGS})
Here, execute_process allows us to get the result of Magick++-config --ldflags into a variable, which we can pass as flags to the linker through target_link_libraries.
Also, note how I've used target_compile_features rather than setting the global CMAKE_CXX_FLAGS variable, target_compile_definitions rather than add_definitions and target_include_directories rather than include_directories. It's better to use local (target-based) commands rather than modifying global state, both in programming and in CMake, since they can have unforeseen repercussions down the line -- in the context of CMake, those global commands would have affected nested sub-projects.
ForgottenUbrella 's version which I adapted didn't quite work for me, copying a line in from another project fixed it. Note, I'm using c++20 not 11.
I had the following error:
..... undefined reference to symbol 'pthread_create##GLIBC_2.2.5'
and the line that fixed it:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2a -pthread")