Error in converting argument from 'const_Ty' to const custom struct - c++11

I have a custom comparator and I pass in two const references of a custom struct to be compared, however, I get the following error:
'bool cmp::operator()(const LogObjects &, const LogObjects &)' cannot convert argument 2 from 'const_Ty' to 'const LogObjects &'.
I've tried adding and removing const, and references but it didn't work.
bool cmp::operator()(const LogObjects &a, const LogObjects &b) { // body }
struct LogObjects {
string category;
string message;
string timestamp;
long long int time;
int entry_id;
sort(master.begin(), master.end(), cmp());
auto it1 = lower_bound(master.begin(), master.end(), time, cmp());
auto it2 = upper_bound(master.begin(), master.end(), time, cmp());
};
(master is a vector of LogObjects and time is a long long int)

Just so the question can be closed, answering here as well.
time is a long long int
Is why you are getting the error.
lower_bound and upper_bound try to compare item in your vector( of type LogObject) with time (of type long long). Easiest way to fix would be to create LogObject timeObj and pass that to lower/upperBound. (If cmp depends on time only)
something like this:
LogObjects timeObject;
timeObject.time = time;
auto it1 = lower_bound(master.begin(), master.end(), timeObject, cmp());
auto it2 = upper_bound(master.begin(), master.end(), timeObject, cmp());

Related

C2664 cannot convert to && value

The compiler wants my lvalue to be a rvalue reference and I dont see why.
My questions are:
Why is "dataLen" const, even though it was declared non const and the lambda is told to catch by reference as default?
Why does the compiler try to convert to rvalue reference "unsigned __int64 &&", even though it was declared "unsigned long long" (no rvalue reference) for tupleByteVector_content?
I think it is because of the lambda capture, but please see this simplified workflow below:
void read_socket()
{
std::vector<std::tuple<unsigned long long, std::vector<unsigned char>>> tupleByteVector_content;
read_socket_readSome(tupleByteVector_content, [this, &tupleByteVector_content]() {
//use tuple vector
});
}
//catch the tuple vector by reference
void read_socket_readSome(std::vector<std::tuple<unsigned long long, const std::shared_ptr<Session>& session, std::vector<unsigned char>>> & tupleByteVector_content, std::function<void()> && continueReadFunction)
{
//Read data length from a asio socket
std::shared_ptr<asio::streambuf> len_buffer = std::make_shared<asio::streambuf>();
asio::async_read(session->connection->socket->next_layer(), *len_buffer, asio::transfer_exactly(1), [&,
this, session, len_buffer, tupleByteVector_content, continueReadFunction](const error_code& ec, std::size_t bytes_transferred) {
//the first value I want to save
unsigned long long dataLen = BytesToLength(len_buffer);
//Read data from a asio socket
std::shared_ptr<asio::streambuf> data_buffer = std::make_shared<asio::streambuf>();
asio::async_read(session->connection->socket->next_layer(), *data_buffer, asio::transfer_exactly(dataLen), [&, this, dataLen, data_buffer, tupleByteVector_content, session, continueReadFunction](const error_code& ec, std::size_t bytes_transferred) {
//ERROR HERE: ----------->
std::tuple<unsigned long long, std::vector<unsigned char>> t =
std::make_tuple<unsigned long long, std::vector<unsigned char>>(
dataLen, // ERROR C2664, cant convert argument 1 from "const unsigned __int64" to "unsigned __int64 &&"
{ asio::buffers_begin(data_buffer->data()), asio::buffers_end(data_buffer->data()) });
//ERROR HERE: <-----------
tupleByteVector_content.push_back(t);
continueReadFunction();
});
});
}
EDIT:
I was able to compile this tuple:
std::tuple<unsigned long long, std::vector<unsigned char>> t = { dataLen, { asio::buffers_begin(data_buffer->data()), asio::buffers_end(data_buffer->data()) } };
But then the push_back to the vector gives the error:
error C2663: [...] ::push_back": for 2 overloads there is no conversion for the this-pointer (free translation into english from myself)
dataLen is treated as const because you capture it by value:
[&, this, dataLen,
^^^
By default function call operator generated for closure is marked as const, so inside const method you can only read data. Modifications are not allowed, unless you add mutable to definition of lambda.
When you use make_tuple you should rely on template argument deduction instead putting types in explicit way, as you did it. Short version of your issue:
int i;
std::tuple<int> t = std::make_tuple<int>(i);
i is named object, so it is lvalue. By make_tuple<int> you make make_tuple signature look like: make_tuple(int&&). This is the place where compiler complains, because i as lvalue cannot be bound to rvalue reference. With argument deduction, parameter of make_tuple is deduced to be: int&, and in this case i can be bound.
push_back on vector doesn't work, because again you captured vector by value. push_back modifies object, which is not allowed when calling on const object. You should capture it by reference.

Using coeffRef with const CwiseUnaryView - Failing when multiplying two CWiseUnaryViews

I'm having some trouble when using coeffRef() with a CWiseUnaryView function, but only when the function is declared as const
Reproducible example:
#include <Eigen/Core>
struct dummy_Op {
EIGEN_EMPTY_STRUCT_CTOR(dummy_Op)
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE const double&
operator()(const double &v) const { return v; }
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE double&
operator()(double &v) const { return v; }
};
void foo(Eigen::MatrixXd &out)
{
//Compiles
Eigen::CwiseUnaryView<dummy_Op, Eigen::MatrixXd> view(out);
view.coeffRef(0,0);
//Doesn't Compile
const Eigen::CwiseUnaryView<dummy_Op, Eigen::MatrixXd> const_view(out);
const_view.coeffRef(0,0);
}
Returns:
<source>: In function 'void foo(Eigen::MatrixXd&)':
<source>:21:28: error: passing 'const Eigen::CwiseUnaryView<dummy_Op,
Eigen::Matrix<double, -1, -1> >' as 'this' argument discards qualifiers
[-fpermissive]
const_view.coeffRef(0,0);
^
In file included from /opt/compiler-explorer/libs/eigen/v3.3.4/Eigen/Core:413,
from <source>:1:
/opt/compiler-explorer/libs/eigen/v3.3.4/Eigen/src/Core/DenseCoeffsBase.h:340:33: note:
in call to 'Eigen::DenseCoeffsBase<Derived, 1>::Scalar&
Eigen::DenseCoeffsBase<Derived, 1>::coeffRef(Eigen::Index, Eigen::Index)
[with Derived = Eigen::CwiseUnaryView<dummy_Op, Eigen::Matrix<double,
-1, -1> >; Eigen::DenseCoeffsBase<Derived, 1>::Scalar = double; Eigen::Index = long int]'
EIGEN_STRONG_INLINE Scalar& coeffRef(Index row, Index col)
^~~~~~~~
Compiler returned: 1
Compiler explorer: https://godbolt.org/z/kPHPuC
The side-effect of this, is that the multiplication of two (non-const) CWiseUnaryViews also fails, see example here: https://godbolt.org/z/JYQb3d
The bottom line is that you're calling a non-const method of a constant instance. The (first) coeffRef that is being called is the one (and only) in DenseCoeffsBase.h (DenseCoeffsBase<Derived, WriteAccessors>), which is not const qualified. The DenseCoeffsBase<Derived, ReadOnlyAccessors> class does not have a coeffRef method. You can get around this error (and get a warning) if you enable the -fpermissive compiler flag.
In the dense case, you probably want to use the operator()(Index, Index) method anyway, which does have a const qualified version. I just noticed the documentation explicitly says to use that method anyway, even for the non-const version. This is obviously not going to return a const reference, but at least in your example as a double, it shouldn't matter too much.
CwiseUnaryView is intended to be used for L-value like expression, e.g.,
MatrixXcd A;
A.real() = something; // `A.real()` is writable
If you want to apply an element-wise functor and use it as an R-value, you should use CwiseUnaryOp instead:
void foo(Eigen::MatrixXd &out)
{
Eigen::CwiseUnaryOp<dummy_Op, Eigen::MatrixXd> view1(out);
// shorter:
auto view2 = out.unaryExpr(dummy_Op());
Eigen::MatrixXd result = view1 * view2;
// or directly write: out.unaryExpr(dummy_Op()) * out.unaryExpr(dummy_Op());
}

Is there a way to create unique type Id at compile time in C++

I can create a unique type id the following way:
template<typename T>
struct TypeId
{
static size_t value()
{
return reinterpret_cast<size_t>(&TypeId<T>::value);
}
};
auto intType = TypeId<int>::value();
It works at runtime but is there a way to do it at compile time ?
I would like to use it in a switch statement like this:
switch (typeId)
{
case TypeId<int>::value():
// do something
break;
case TypeId<double>::value():
// do something
break;
case TypeId<MyClass>::value():
// do something
break;
}
The problem here is that I cannot convert a pointer to the size_t at compile time:
template<typename T>
struct TypeId
{
static constexpr size_t value()
{
return reinterpret_cast<size_t>(&TypeId<T>::value);
}
};
constexpr auto id = TypeId<int>::value();
The example above gives the following error:
error: conversion from pointer type ‘size_t (*)() {aka long unsigned int (*)()}’ to arithmetic type ‘size_t {aka long unsigned int}’ in a constant expression
constexpr auto id = TypeId<int>::value();
UPDATE
I would like to understand why returning an address is fine in a constexpr but converting it to an int is not. The following code compiles (but I cannot use pointers in a switch statement):
template<typename T>
struct TypeId
{
static constexpr void* value()
{
return reinterpret_cast<void*>(&TypeId<T>::value);
}
};
constexpr void* id = TypeId<int>::value();
std::cout << "id: " << id << std::endl;
This sounds like an XY problem. If you want to get compile-time type information, then use compile-time ways to do this. The right way to do this is with std::is_same.
if(std::is_same<int, T>::value) {
// do something
} else if (std::is_same<double, T>::value) {
// do something else
} // ...
This can cause certain problems. if you're using methods for specific types, like std::string::length() in your conditions, you'll have a compile error. There are ways to solve this:
Use if constexpr
Use std::enable_if to create template specializations that are dependent on the type
If you have only pointer-type problems, you have to reinterpret_cast all your pointers to T
There is currently no way in C++ to automatically allocate a unique integer type id and make it availabe compile time.
This is why libraries that need it use manual type registration, e.g.:
template<class T> struct TypeId;
#define REGISTER_TYPE_ID(T, id_value) template<> struct TypeId<T> { static constexpr int id = id_value; };
REGISTER_TYPE_ID(bool, 1)
REGISTER_TYPE_ID(char, 2)
REGISTER_TYPE_ID(unsigned char, 3)
REGISTER_TYPE_ID(unsigned short, 4)
REGISTER_TYPE_ID(unsigned int, 5)
REGISTER_TYPE_ID(unsigned long, 6)
REGISTER_TYPE_ID(unsigned long long, 7)
REGISTER_TYPE_ID(signed char, 8)
REGISTER_TYPE_ID(signed short, 9)
REGISTER_TYPE_ID(signed int, 10)
REGISTER_TYPE_ID(signed long, 11)
REGISTER_TYPE_ID(signed long long, 12)
REGISTER_TYPE_ID(float, 13)
REGISTER_TYPE_ID(double, 14)
REGISTER_TYPE_ID(long double, 15)

C++11 Check two sets of variadic template arguments match

This question relates to an earlier one I asked regarding implementing something akin to Qt's signal/slots in C++11.
Consider the following (very simplified signal dispatcher, that in this example does nothing of any use, it's just to demonstrate the pattern/problem):
template< typename... TYPES >
class Signal
{
public:
Signal() = default;
~Signal() = default;
template< typename... PARAMETERS >
void broadcast( PARAMETERS &&... p )
{
// static_assert to confirm PARAMETERS can map to TYPES
}
};
This works well enough, but there's some unwanted type conversion going on in practice. e.g.;
// acceptable use.
Signal< int, unsigned, float, char >().broadcast( 1, 2u, 0.f, 'a' );
// should fail compilation, first parameter is a float, 4th is an int.
Signal< int, unsigned, float, char >().broadcast( 0.f, 0, 0.f, 0 );
// acceptable use, first parameter is const, but it's convertible.
const int i = 3;
Signal< int, unsigned, float, char >().broadcast( i, 2u, 0.f, 'a');
// acceptable use, first parameter is const &, but it's convertible.
const int & j = i;
Signal< int, unsigned, float, char >().broadcast( j, 2u, 0.f, 'a');
There should be no silent float to int conversion. Conversion of const/const & in this instance should be possible (the format of TYPES should not have const or & as all data should be passed by value).
I'd like to prevent compilation where such unwanted type conversion happens. I thought to wrap up both TYPES and PARAMETERS in tuples, iterate over the tuple and confirm that each type in a given tuple parameter index matches (including using std::decay), but then I couldn't see a way to do that at compile time so that it could go in a static_assert.
For reference, compilers of choice are clang (latest on OS X 7.3 (clang-703.0.31)) and vc14.
Is what I want to do possible and, if so, can anyone offer any pointers?
Using (once again) the all_true bool pack trick from Columbo:
template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
template <class... Args>
struct Signal {
template <class... Dargs, class = typename std::enable_if<all_true<
std::is_same<Args, typename std::decay<Dargs>::type>{}...
>{}>::type>
void broadcast(Dargs &&...) {}
};
This SFINAE's away the function if the parameters don't match exactly.
Here is a metaprogram I quickly came up with. It is a bit coarse, but can be implemented in a more better way. You should probably use the decayed type (std::decay) in the metaprogram to get correct result.
#include <iostream>
#include <type_traits>
template <typename... T> struct param_pack {};
template <typename, typename> struct is_all_same_impl;
template <>
struct is_all_same_impl<param_pack<>, param_pack<>>
{
static bool const value = true;
};
template <typename T, typename S, typename... Rest, typename... SRest>
struct is_all_same_impl<param_pack<T, Rest...>, param_pack<S, SRest...>>
{
static bool const value = false;
};
template <typename T, typename... Rest, typename... SRest>
struct is_all_same_impl<param_pack<T, Rest...>, param_pack<T, SRest...>>
{
static bool const value = is_all_same_impl<param_pack<Rest...>, param_pack<SRest...>>::value;
};
template <typename, typename>
struct is_all_same;
template <typename... FSet, typename... SSet>
struct is_all_same<param_pack<FSet...>, param_pack<SSet...>>: is_all_same_impl<param_pack<FSet...>, param_pack<SSet...>> {};
int main() {
std::cout << is_all_same<param_pack<int, char, float>, param_pack<int, char, int>>::value << std::endl;
return 0;
}
UPDATE :: More simpler version
template <typename... T> struct param_pack {};
int main() {
std::cout << std::is_same<param_pack<int, float, int>, param_pack<int,float,int>>::value << std::endl;
return 0;
}
So you can do something like:
static_assert( is_same<param_pack<Args...>, param_pack<std::decay_t<Dargs>...>>::value, "Parameters do not sufficiently match." );

Length of user-defined string literal as a template argument?

Is there any way to get behavior like this?
// Some definition(s) of operator "" _my_str
// Some definition of function or macro MY_STR_LEN
using T1 = MY_STR_LEN("ape"_my_str);
// T1 is std::integral_constant<std::size_t, 3U>.
using T2 = MY_STR_LEN("aardvark"_my_str);
// T2 is std::integral_constant<std::size_t, 8U>.
It seems not, since the string literals are passed immediately to some_return_type operator "" _my_str(const char*, std::size_t); and never to a literal operator template (2.14.8/5). That size function parameter can't be used as a template argument, even though it will almost always be a constant expression.
But it seems like there ought to be some way to do this.
Update: The accepted answer, that this is not possible without an extra definition per literal, is accurate for C++11 as asked, and also C++14 and C++17. C++20 allows the exact result asked for:
#include <cstdlib>
#include <type_traits>
#include <string_view>
struct cexpr_str {
const char* ptr;
std::size_t len;
template <std::size_t Len>
constexpr cexpr_str(const char (&str)[Len]) noexcept
: ptr(str), len(Len) {}
};
// Essentially the same as
// std::literals::string_view_literals::operator""sv :
template <cexpr_str Str>
constexpr std::string_view operator "" _my_str () noexcept
{
return std::string_view(Str.ptr, Str.len);
}
#define MY_STR_LEN(sv) \
std::integral_constant<std::size_t, (sv).size()>
Reading C++11 2.14.8 carefully reveals that the "literal operator template" is only considered for numeric literals, but not for string and character literals.
However, the following approach seems to give you constexpr access to the string length (but not the pointer):
struct MyStr
{
char const * str;
unsigned int len;
constexpr MyStr(char const * p, unsigned int n) : str(p), len(n) {}
};
constexpr MyStr operator "" _xyz (char const * s, unsigned int len)
{
return MyStr(s, len);
}
constexpr auto s = "Hello"_xyz;
Test:
#include <array>
using atype = std::array<int, s.len>; // OK

Resources