I'm got a map of key type std::pair<Foo,Bar> and value in which I would like to insert into a map by passing the pair std::pair<std::pair<Foo,Bar> , int> to the insert function like so (online source)
struct Foo{};
struct Bar{};
typedef std::pair<Foo,Bar> FooBar;
typedef std::pair<FooBar,int> FooBarPair;
typedef std::map<FooBar,int> FooBarMap;
struct FooBarData
{
operator const FooBarPair() const
{
return std::make_pair( std::make_pair( m_foo , m_bar ) , m_num );
}
private:
int m_num;
Foo m_foo;
Bar m_bar;
};
int main()
{
FooBarData fbd;
FooBarMap fbm;
fbm.insert( fbd );
}
clang error message
/usr/include/c++/v1/map:1041:9: note: candidate function not viable: no known conversion from 'FooBarData' to 'const value_type' (aka 'const pair<const key_type, mapped_type>') for 1st argument
insert(const value_type& __v) {return __tree_.__insert_unique(__v);}
^
/usr/include/c++/v1/map:1050:14: note: candidate function template not viable: requires 2 arguments, but 1 was provided
void insert(_InputIterator __f, _InputIterator __l)
^
/usr/include/c++/v1/map:1045:9: note: candidate function not viable: requires 2 arguments, but 1 was provided
insert(const_iterator __p, const value_type& __v)
Is there any fix along these lines?
Add missing operator <.
Also, remove const from return type of conversion operator.
Edit After your change in Q:
You have to change your conversion to
operator std::pair<const FooBar, int>() const
Else, it would require 2 user conversions, which is not allowed.
Demo
(At least sometimes), the map implementations are/were red black trees. For map insert to work, your key type needs to support comparison (operator <). I cannot see this requirement to be met for your empty structs and the pair you create from them.
So as a first sanity check, I would replace Foo and Bar structs with
typedef int Foo;
typedef int Bar;
in order to see if something else is wrong with your code.
If it still is not compiling, check if std::pair<> supports comparison.
Also, instead of typedef'ing the FooBarPair yourself, you can simply enjoy that the map template already did that for you. For example:
...
operator FooBarMap::value_type() {
...
}
Here a fixed version, which compiles:
#include <map>
struct Foo { int x; };
struct Bar {};
typedef std::pair<Foo, Bar> FooBar;
typedef std::map<FooBar, int> FooBarMap;
bool operator <(const FooBarMap::key_type&lhs, const FooBarMap::key_type& rhs)
{
return lhs.first.x < rhs.first.x;
}
struct FooBarData
{
operator FooBarMap::value_type() const
{
return FooBarMap::value_type(FooBarMap::key_type(m_foo, m_bar), m_num);
}
private:
int m_num;
Foo m_foo;
Bar m_bar;
};
int main()
{
FooBarData fbd;
FooBarMap fbm;
fbm.insert(fbd);
}
Related
I can't understand how i can create expr object from double in expr.cpp file.
expr_base:
The base class of all expressions. Note that all expression classes
(including this base) are private to the implementation and should not
be exposed to other code. The rest of the program should use
expressions only via expr.
This subclasses std::enable_shared_from_this to enable getting
shared_ptr to this from a method.
expr:
Wrapper around dynamically allocated instances of expr_base. This type
has value semantics and since all subclasses of expr_base are
immutable, shallow copies are made.
This type has overloaded functions and operators, so that expression
construction is easy and readable.
error:
error: no viable conversion from returned value of type 'typename enable_if<!is_array<number>::value,
shared_ptr<number> >::type' (aka 'std::__1::shared_ptr<exprs::number>') to function return type 'expr'
return std::make_shared<exprs::number>(n);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/..../expr.hpp(...): note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'typename enable_if<!is_array<number>::value, shared_ptr<number> >::type' (aka 'std::__1::shared_ptr<exprs::number>') to 'const expr &' for 1st argument
class expr final {
^
/.../expr.hpp:(...): note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'typename enable_if<!is_array<number>::value, shared_ptr<number> >::type' (aka 'std::__1::shared_ptr<exprs::number>') to 'expr &&' for 1st argument
/.../expr.hpp:(...): note: candidate template ignored: requirement 'std::is_convertible<exprs::number *, const expr_base*>::value' was not satisfied [with T = exprs::number]
expr(std::shared_ptr<T> e): ptr(std::static_pointer_cast<const expr_base>(std::move(e))) {}
expr.hpp
...
class expr;
class expr_base: public std::enable_shared_from_this<expr_base>
{
friend class expr;
protected:
expr_base() = default;
public:
using variable_map_t = std::map<std::string, double>;
virtual ~expr_base() = default;
};
class expr final {
private:
using const_pointer = std::shared_ptr<const expr_base>;
public:
using variable_map_t = expr_base::variable_map_t;
template <typename T, typename = std::enable_if_t<std::is_convertible<T*, const expr_base*>::value>>
expr(std::shared_ptr<T> e): ptr(std::static_pointer_cast<const expr_base>(std::move(e))) {}
expr() = default;
static expr number(double n);
operator const_pointer const &() const {return ptr;}
const expr_base* operator->() const {assert(ptr.get() != nullptr); return ptr.get();}
private:
const_pointer ptr;
};
expr.cpp
...
#include "expr.hpp"
#include "expr_impl.hpp"
expr expr::number(double n) {
return std::make_shared<exprs::number>(n); // It doesn't work
}
expr_impl.hpp
...
#include "expr.hpp"
namespace exprs {
class number:expr_base {
private:
double num_;
public:
number(double num): num_(num) {};
};
}
The following code compiles perfectly if:
I don't include <iostream> or
I name operator== as alp::operator==.
I suppose there is a problem with <iostream> and operator==, but I don't know what.
I compile the code with gcc 7.3.0, clang++-6.0 and goldbolt. Always the same error.
The problem is that the compiler is trying to cast the parameters of operator== to const_iterator, but why? (I suppose the compiler doesn't see my version of operator==, and looks for other versions).
#include <vector>
#include <iostream> // comment and compile
namespace alp{
template <typename It_base>
struct Iterator {
using const_iterator = Iterator<typename It_base::const_iterator>;
operator const_iterator() { return const_iterator{}; }
};
template <typename It_base>
bool operator==(const Iterator<It_base>& x, const Iterator<It_base>& y)
{ return true;}
}// namespace
struct Func{
int& operator()(int& p) const {return p;}
};
template <typename It, typename View>
struct View_iterator_base{
using return_type = decltype(View{}(*It{}));
using const_iterator =
View_iterator_base<std::vector<int>::const_iterator, Func>;
};
using view_it =
alp::Iterator<View_iterator_base<std::vector<int>::iterator, Func>>;
int main()
{
view_it p{};
view_it z{};
bool x = operator==(z, p); // only compiles if you remove <iostream>
bool y = alp::operator==(z,p); // always compile
}
Error message:
yy.cpp: In instantiation of ‘struct View_iterator_base<__gnu_cxx::__normal_iterator<const int*, std::vector<int> >, Func>’:
yy.cpp:9:73: required from ‘struct alp::Iterator<View_iterator_base<__gnu_cxx::__normal_iterator<const int*, std::vector<int> >, Func> >’
yy.cpp:44:29: required from here
yy.cpp:28:42: error: no match for call to ‘(Func) (const int&)’
using return_type = decltype(View{}(*It{}));
~~~~~~^~~~~~~
yy.cpp:22:10: note: candidate: int& Func::operator()(int&) const <near match>
int& operator()(int& p) const {return p;}
^~~~~~~~
yy.cpp:22:10: note: conversion of argument 1 would be ill-formed:
yy.cpp:28:42: error: binding reference of type ‘int&’ to ‘const int’ discards qualifiers
using return_type = decltype(View{}(*It{}));
~~~~~~^~~~~~~
I've made a more minimal test case here: https://godbolt.org/z/QQonMG .
The relevant details are:
A using type alias does not instantiate a template. So for example:
template<bool b>
struct fail_if_true {
static_assert(!b, "template parameter must be false");
};
using fail_if_used = fail_if_true<true>;
will not cause a compile time error (if fail_if_used isn't used)
ADL also inspects template parameter classes. In this case, std::vector<int>::iterator is __gnu_cxx::__normal_iterator<const int*, std::vector<int> >, Func>, which has a std::vector<int> in it's template. So, operator== will check in the global namespace (always), alp (As alp::Iterator is in alp), __gnu_cxx and std.
Your View_iterator_base::const_iterator is invalid. View_iterator_base::const_interator::result_type is defined as decltype(Func{}(*std::vector<int>::const_iterator{})). std::vector<int>::const_iterator{} will be a vectors const iterator, so *std::vector<int>::const_iterator{} is a const int&. Func::operator() takes an int&, so this means that the expression is invalid. But it won't cause a compile time error if not used, for the reasons stated above. This means that your conversion operator is to an invalid type.
Since you don't define it as explicit, the conversion operator (To an invalid type) will be used to try and match it to the function parameters if they don't already match. Obviously this will finally instantiate the invalid type, so it will throw a compile time error.
My guess is that iostream includes string, which defines std::operator== for strings.
Here's an example without the std namespace: https://godbolt.org/z/-wlAmv
// Avoid including headers for testing without std::
template<class T> struct is_const { static constexpr const bool value = false; } template<class T> struct is_const<const T> { static constexpr const bool value = true; }
namespace with_another_equals {
struct T {};
bool operator==(const T&, const T&) {
return true;
}
}
namespace ns {
template<class T>
struct wrapper {
using invalid_wrapper = wrapper<typename T::invalid>;
operator invalid_wrapper() {}
};
template<class T>
bool operator==(const wrapper<T>&, const wrapper<T>&) {
return true;
}
}
template<class T>
struct with_invalid {
static_assert(!is_const<T>::value, "Invalid if const");
using invalid = with_invalid<const T>;
};
template<class T>
void test() {
using wrapped = ns::wrapper<with_invalid<T>>;
wrapped a;
wrapped b;
bool x = operator==(a, b);
bool y = ns::operator==(a, b);
}
template void test<int*>();
// Will compile if this line is commented out
template void test<with_another_equals::T>();
Note that just declaring operator const_iterator() should instantiate the type. But it doesn't because it is within templates. My guess is that it is optimised out (where it does compile because it's unused) before it can be checked to show that it can't compile (It doesn't even warn with -Wall -pedantic that it doesn't have a return statement in my example).
Catch2 gives a Predicate class to make our own matcher. https://github.com/catchorg/Catch2/blob/master/docs/matchers.md
I simply test an unordered_map(decltype(getEntity2IdMap()) here.
namespace Generic {
Predicate<decltype(getEntity2IdMap())>(
[&](auto& maps) -> bool {
return maps.size() == 3 &&
maps["entity1"] == 0 &&
maps["entity2"] == 1 &&
maps["entity3"] == 2; },
"entities were inserted."));
The Predicate class has a simple definition.
template <typename T>
class PredicateMatcher : public MatcherBase<T> {
std::function<bool(T const&)> m_predicate;
std::string m_description;
public:
PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
:m_predicate(std::move(elem)),
m_description(Detail::finalizeDescription(descr))
{}
bool match( T const& item ) const override {
return m_predicate(item);
}
std::string describe() const override {
return m_description;
}
};
} // namespace Generic
// The following functions create the actual matcher objects.
// The user has to explicitly specify type to the function, because
// infering std::function<bool(T const&)> is hard (but possible) and
// requires a lot of TMP.
template<typename T>
Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
return Generic::PredicateMatcher<T>(predicate, description);
}
However, clang++ yields a type mismatch.
error: no viable overloaded operator[] for type 'const std::__1::unordered_map<std::__1::basic_string<char>,
unsigned int, std::__1::hash<std::__1::basic_string<char> >, std::__1::equal_to<std::__1::basic_string<char> >,
std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, unsigned int> > >'
I am wondering the maps type here or I misunderstood the lambda context for "/m/entity1".
The full error message is likely to be something like:
<source>:7:21: error: no viable overloaded operator[] for type 'const std::unordered_map<std::string, int>' (aka 'const unordered_map<basic_string<char>, int>')
std::cout << map["test" ] == 1;
~~~^~~~~~~
unordered_map.h:963:7: note: candidate function not viable: 'this' argument has type 'const std::unordered_map<std::string, int>' (aka 'const unordered_map<basic_string<char>, int>'), but method is not marked const
operator[](const key_type& __k)
^
unordered_map.h:967:7: note: candidate function not viable: 'this' argument has type 'const std::unordered_map<std::string, int>' (aka 'const unordered_map<basic_string<char>, int>'), but method is not marked const
operator[](key_type&& __k)
The key clue is 'this' argument has type 'const.... but method is not marked const.
Your maps are const but operator[] is not const, you need to use find() or at() to retrieve values from a const std::map or std::unordered_map.
I kind of need help! I want to define a template method for my class to access its private fields. Here is my code:
#include <string>
#include <vector>
using namespace std;
class ex
{
public:
ex(string pegah_,int amin_):pegah(pegah_),amin(amin_){}
template<typename T>
T get_field(){
if(is_same<T,string>::value)
return pegah;
else if(is_same<T,int> ::value)
return amin;
}
private:
string pegah;
int amin;
};
int main(void)
{
string i = "salam";
int o=10;
ex y(i,o);
y.get_field<string>();
}
as you see I want to use just one function. But I keep getting this error:
test.cpp: In instantiation of ‘T ex::get_field() [with T = std::basic_string<char>]’:
test.cpp:30:21: required from here
test.cpp:15:8: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
return amin;
^
In file included from /usr/include/c++/4.8/string:52:0,
from test.cpp:1:
/usr/include/c++/4.8/bits/basic_string.h:490:7: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ [-fpermissive]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
can anyone help?
Instead you could lay your code out like this:
template<typename T> T get_field();
// outside the class:
template<> inline int ex::get_field<int>() { return amin; }
template<> inline string ex::get_field<string>() { return pegah; }
As you have it now, all branches of the if..else must compile.
Basically you have three options to do it.
First using explicit specialization of template member function.
class Foo {
public:
template <typename T>
T get () const;
private:
std::string str {"XXX"};
int value {42};
};
template <>
inline std::string Foo::get () const {
return str;
}
template <>
inline int Foo::get () const {
return value;
}
Second one is to use helper function with different parameters type.
class Foo2 {
public:
template <typename T>
T get () const {
return get_helper (typename std::is_same<T, std::string>::type {});
}
private:
std::string get_helper (std::true_type) const {
return str;
}
int get_helper (std::false_type) const {
return value;
}
private:
std::string str {"YYY"};
int value {44};
};
Third option is to use SFINAE.
class Foo3 {
public:
template <typename T>
typename std::enable_if<std::is_same<T, std::string>::value, T>::type get () const {
return str;
}
template <typename T>
typename std::enable_if<std::is_same<T, int>::value, T>::type get () const {
return value;
}
private:
std::string str {"ZZZ"};
int value {45};
};
and usage would be like:
template <typename T>
void show (T v) {
std::cout << v << std::endl;
}
Foo f1;
show (f1.get<std::string> ());
show (f1.get<int> ());
Foo2 f2;
show (f2.get<std::string> ());
show (f2.get<int> ());
Foo3 f3;
show (f3.get<std::string> ());
show (f3.get<int> ());
Second option is helpful when you want to distinguish between two types. If you have more getters, then probably you will need to use first or third option.
I think it is better you define a getter and setter for each field. That is a better approach. It's easier to read and to understand and you achieve the same as with the template technique.
Explanation of your code:
It does not compile because of type checking. Template functions are generated when used in C++11. You use it with template parameter string so the function is generated. The problem is that you generate a function that returns T as a string, but you have code in your function that returns int (variable amin). Generate the function in your mind like so for T equals string:
string get_field(){
if(is_same<string,string>::value)
return pegah; // OK
else if(is_same<string,int> ::value)
return amin; // NOT OK, amin is of type int
}
One solution is that of M.M, it's called specialization. You specialize a template for (a) specific argument(s). And there are also other answers coming up.
I do not recommend that, because you finally do nothing else but generating getter functions for each variable in a specialized template. You could as well just have written:
string get_pegah(){ return pegah; }
int get_amin() { return amin; }
Easier to read, to maintain and straight forward. And more efficient I think.
as you see I want to use just one function
You don't really. You either call get_field<string> or get_field<int> and when called the appropriate function would be generated; either with T=string, T=int or both (depending on your use case). Though as you have learned by now, it's an error to do so in that case.
What you probably meant was that you want to have one function definition to do what you want. I don't think that is possible.
I am unable to write a correct user defined conversion for a type Item. This is what I've tried:
#include <iostream>
#include <boost/optional.hpp>
struct A
{
int x;
};
struct Item
{
boost::optional<int> x_;
Item(){}
Item(const A& s)
: x_(s.x)
{
}
operator boost::optional<A>() const {
boost::optional<A> s;
if (x_) {
s->x = *x_;
}
return s;
}
};
std::vector<A> getA(const std::vector<Item> &items) {
std::vector<A> a;
for (const auto &i : items) {
if (i.x_) {
a.push_back(*static_cast<boost::optional<A>>(i)); // <- this line causes error
}
}
return a;
}
That is how I use it:
int main() {
A a;
a.x = 3;
Item i(a);
auto v = getA({i});
return 0;
}
g++ -std=c++11 says:
In file included from /usr/include/boost/optional.hpp:15:0,
from test.cpp:2:
/usr/include/boost/optional/optional.hpp: In instantiation of ‘void boost::optional_detail::optional_base<T>::construct(const Expr&, const void*) [with Expr = Item; T = A]’:
/usr/include/boost/optional/optional.hpp:262:25: required from ‘boost::optional_detail::optional_base<T>::optional_base(const Expr&, const Expr*) [with Expr = Item; T = A]’
/usr/include/boost/optional/optional.hpp:559:78: required from ‘boost::optional<T>::optional(const Expr&) [with Expr = Item; T = A]’
test.cpp:30:55: required from here
/usr/include/boost/optional/optional.hpp:392:8: error: no matching function for call to ‘A::A(const Item&)’
new (m_storage.address()) internal_type(expr) ;
^
/usr/include/boost/optional/optional.hpp:392:8: note: candidates are:
test.cpp:3:8: note: A::A()
struct A
^
test.cpp:3:8: note: candidate expects 0 arguments, 1 provided
test.cpp:3:8: note: constexpr A::A(const A&)
test.cpp:3:8: note: no known conversion for argument 1 from ‘const Item’ to ‘const A&’
test.cpp:3:8: note: constexpr A::A(A&&)
test.cpp:3:8: note: no known conversion for argument 1 from ‘const Item’ to ‘A&&’
Why does it try to find A struct constructor instead of use user defined conversion operator?
You may point me directly to any position of the user-defined conversion page because I am unable to find any reason for this. For example,
User-defined conversion function is invoked on the second stage of the implicit conversion, which consists of zero or one converting constructor or zero or one user-defined conversion function.
in my opinion directly says that if no conversion constructor is defined then user-defined conversion function will be used. Am I wrong? And if yes, how can I implement user-defined conversion then without defining conversion cunstructor in struct A ?
You have two issues with your code. Your optional operator never initializes the boost::optional. If you don't do that, accessing members is undefined behavior. What you have to do is:
operator boost::optional<A>() const {
boost::optional<A> s;
if (x_) {
s = A{*x_};
}
return s;
}
The second issue is when you do:
static_cast<boost::optional<A>>(i);
That is equivalent to:
boost::optional<A> __tmp(i);
But it turns out that boost::optional has an explicit template constructor. That will be preferred to your conversion function. The error you're seeing is the compiling going down the path of this factory constructor, where Item is not such a factory.
You could simply use boost::optional<A> directly:
std::vector<A> getA(const std::vector<Item> &items) {
std::vector<A> a;
for (boost::optional<A> opt : items) {
if (opt) {
a.push_back(*opt);
}
}
return a;
}
Or, since the constructor template is explicit, you could use the conversion operator in a non-explicit context:
boost::optional<A> opt = i;
a.push_back(*opt);
This has the added benefit of also being easier to read.