I'm pretty new in C++. I have wrote a function template to sum all elements in a vector like this:
template<typename T>
inline T sumator(const std::vector<T> &sequence) {
T init = T{};
return accumulate(sequence.begin(), sequence.end(), init);
}
All work well until the default constructor is not declare, but declare constructor from, for example, 2 arguments.
Like this:
class A {
private:
int a;
int b;
public:
// A() = default;
A(int aa, int bb) : a(aa),b(bb){};
A operator+(const A &right) const {
return {a + right.a, b + right.b};
}
bool operator==(const A &right) const {
return (a == right.a && b == right.b);
}
};
vector<A> bc = {{3,5},{5,5}};
A res = Adder::sumator(works);
A result = {8,10};
assert(result,res);
Now I get an error like : error: no matching constructor for initialization of 'A'
T init = T{};
How can I avoid this situation, not using https://en.cppreference.com/w/cpp/types/is_default_constructible
UPD: I have many classes, some of them with default constructor, some without but with constructor for 2 arg, some for 3, e.t.c. And I want to accumulate every situation well
Possible solutions that I can think of.
Let users rely on std::accumulate by providing an initial vlaue.
Provide an overload of sumator with an initial value. Users can call the overload with an initial value if they have a type that does not have default constructor.
Insist that the type for which the function is invoked have a default consructor.
template<typename T>
inline T sumator(const std::vector<T> &sequence, T init) {
return accumulate(sequence.begin(), sequence.end(), init);
}
template<typename T>
inline T sumator(const std::vector<T> &sequence) {
return accumulate(sequence.begin(), sequence.end(), {});
}
You can add another parameter with default argument.
template<typename T>
inline T sumator(const std::vector<T> &sequence, const T& init = T{}) {
return accumulate(sequence.begin(), sequence.end(), init);
}
For types could be default-constructed you can still
sumator(some_vector);
And specify the default value when T can't be default-constructed. e.g.
sumator(some_vector, A{0, 0});
You can split it in two overloads and add a static_assert to provide a nice compilation error message if someone tries to use it the wrong way.
One overload would be valid only if the type is default constructible and one overload would be valid for types that is not as well as for those that are:
#include <type_traits>
#include <vector>
template<typename T>
T sumator(const std::vector<T>& sequence) {
static_assert(std::is_default_constructible_v<T>);
return std::accumulate(sequence.begin(), sequence.end(), T{});
}
template<typename T>
T sumator(const std::vector<T>& sequence, const T& init) {
return std::accumulate(sequence.begin(), sequence.end(), init);
}
Another option is to add a default argument that can be used for types that are default constructible - and you could also make it more generic to make it work with not only vectors but with lists etc.
template<template<class, class...> class C, class T, class... Ts>
T sumator(const C<T, Ts...>& sequence, const T& init = T{}) {
return std::accumulate(sequence.begin(), sequence.end(), init);
}
Related
I'm a CS student, and the I have a task where I need some help. The task is to create a vectors_predicate_view class that gets a T type as the first template parameter and a predicate as the second template parameter. In its constructor the class should get 2 std::vectors as parameters.
Here is the class:
#pragma once
#include <vector>
template<typename T, typename Predicate>
class vectors_predicate_view
{
private:
Predicate predict;
std::vector<T> originalContents1;
std::vector<T> originalContents2;
std::vector<T> &original1; // reference to original vector1
std::vector<T> &original2; // reference to original vector2
void setElements(std::vector<T> &vector1, std::vector<T> &vector2)
{
//Putting every element from vector1 into originalContents1
for(auto element : vector1)
originalContents1.push_back(element);
vector1.clear(); //Emptying vector1
//Putting every element from vector2 into originalContents2
for(auto element : vector2)
originalContents2.push_back(element);
vector2.clear(); //Emptying vector2
//We loop through originalContents1
//if the element gives back true for the predictatum, we add it to vector1
//else it goes to vector2
for(auto element : originalContents1)
{
if (predict(element))
vector1.push_back(element);
else
vector2.push_back(element);
}
//We loop through originalContents2
//if the element gives back true for the predictatum, we add it to vector1
for(auto element : originalContents2)
if(predict(element))
vector1.push_back(element);
}
public:
vectors_predicate_view(std::vector<T> &vector1, std::vector<T> &vector2) : original1(vector1), original2(vector2)
{
setElements(vector1, vector2);
}
};
The task is to make the second parameter optional, and if it's not given, the class should not do anything with the 2 given vectors inside its constructor.
Just to give an idea, here is how that second template optimally looks like. It's an std::unary_function that looks like this:
struct is_even: std::unary_function<int, bool>
{
bool operator()(int i) const
{
return 0 == i % 2;
}
};
struct is_good_language: std::unary_function<std::string, bool>
{
bool operator()(const std::string& s) const
{
return s == "C++" || s == "C";
}
};
and called like this:
const vectors_predicate_view<int, is_even> va(a, b);
vectors_predicate_view<std::string, is_good_language> vb(x, y);
Any help would be greatly appreciated!
You can define a predicate that always returns true no matter what the argument is:
struct always_true {
template <typename T>
constexpr bool operator()(T&&) const noexcept {
return true;
}
};
Then, set this predicate to be the default argument for the template parameter Predicate:
template <typename T, typename Predicate = always_true>
// ^^^^^^^^^^^^^ default argument
class vectors_predicate_view {
// ...
};
When the user explicitly supplies an argument, the default argument is ignored.
To differentiate the default case from user-supplies predicates, an alternative approach is to put the tag in a detail namespace — which is private to the implementation, by convention — and use specialization to handle the case:
namespace detail {
struct tag {};
}
template <typename T, typename Predicate = detail::tag>
// ^^^^^ default argument
class vectors_predicate_view {
// normal case
};
template <typename T>
class vectors_predicate_view<T, detail::tag> {
// default case
};
When the user does not provide the second template argument, the specialization is used. This may cause some code duplication, but it gives you full control over what to do in the default case.
Aside: since C++11, there is no need to derive from unary_function, etc. — see Why have unary_function, binary_function been removed from C++11?.
I'm trying to mimic the behavior of tie pre C++11.
pair<int, int> test() {
return make_pair(13, 42);
}
int main() {
int a = 1, b = 2;
pair<int&, int&>(a, b) = test();
cout << a << ' ' << b << endl;
}
This works however if I use make_pair instead to the pair constructor a and b are not assigned.
Why does the pair constructor work but not make_pair?
Actually you can use std::make_pair. But you need to implement reference_wrapper class to imitate reference. Examplary (not very polished, but working as expected) c++03 approach:
#include <iostream>
#include <utility>
using namespace std;
template <class T>
struct reference_wrapper {
bool is_const;
T* v;
T const* cv;
reference_wrapper(T& t): v(&t), is_const(false) { }
reference_wrapper(T const& t): cv(&t), is_const(true) { }
reference_wrapper &operator=(reference_wrapper const &rw) {
if (rw.is_const) {
*v = *rw.cv;
} else {
*v = *rw.v;
}
}
};
template <class T>
reference_wrapper<T> ref(T &t) {
return reference_wrapper<T>(t);
}
pair<int, int> test() {
return make_pair(13, 42);
}
int main() {
int a = 1, b = 2;
//pair<int&, int&>(a, b) = test(); // works
make_pair(ref(a), ref(b)) = test(); // now it does work
std::cout << a << ' ' << b << std::endl;
}
In 20.2.2[lib.pairs]8 the standard states that pair uses "explicit types" while make_pair's "types are deduced".
This is why the standard defines a constructor for pair:
template <class T1, class T2>
pair(const T1& x, const T2& y)
If you run your code on a C++03 compiler you will get this error:
non-static reference member int& std::pair<int&, int&>::first, can't use default assignment operator
The problem is that pair uses an implicitly-declared copy assignment operator which is not defined if the pair:
Has a non-static data member of a reference type
Whether defined by make_pair or the pair constructor, the template arguments will define both of the pair's members as int& so the implicitly-declared copy assignment operator will not be defined. So this cannot be accomplished with a pair in C++03.
If using return parameter is undesirable, you can write your own implementation of tie:
template <class T1, class T2>
struct tie{
T1& first;
T2& second;
tie(T1& x, T2& y) : first(x), second(y) {}
tie<T1, T2>& operator=(const pair<T1, T2>& rhs){
first = rhs.first;
second = rhs.second;
return *this;
}
};
This will allow assignment of a pair:
tie<int, int>(a, b) = test();
To get the exact C++11 behavior which doesn't require template arguments you'll need to define a function. If tie is nested in namespace details the function can be defined as:
template <class T1, class T2>
details::tie<T1, T2> tie(T1& x, T2& y) {
return details::tie<T1, T2>(x, y);
}
This will allow assignment of a pair just as in C++11:
tie(a, b) = test();
Live Example
Note that this is still intolerant of using int& template arguments, so details::tie<int&, int&> and tie<int&, int&> will fail just as before.
make_pair produces a pair of values, not references. That means it would produce pair<int, int> in your example and you'd be assigning results of test() to a temporary variable¹.
You can mimic tie with the following:
template<typename T, typename U>
std::pair<T&, U&> tie_pair(T& l, U& r)
{
return std::pair<T&, U&>(l, r);
}
http://ideone.com/muAcaG
¹ this is an unfortunate side-effect of C++03 not having ref-qualifiers. In C++≥11 you can delete operator= for rvalue this (in non-std classes) and make such cases a compiler error rather than silent surprising behaviour.
I need to use different compare functions as unary functions, where one of the values is embedded inside the comparator. To do so I created an adaptor class, something like:
template<typename T, typename Compare>
class CompareAdaptor : private Compare
{
public:
CompareAdaptor(T value)
: mValue(value)
{
}
bool operator()(T v) const
{
return Compare::operator()(v, mValue);
}
private:
T mValue;
};
and now I can define a new unary comparator like:
template<typename T>
using EqualTo = CompareAdaptor<T, std::equal_to<T>>;
template<typename T>
using LessEqual = CompareAdaptor<T, std::less_equal<T>>;
My questions is: Is there a simpler way(without using the adaptor class) to define those unary comparators? I think this is a very common problem and probably you have better solutions.
In C++11, this is as good as it gets. But I'd rather expect the predicate to be directly constructed at the call site :
std::find_if(begin(v), end(v), [limit](int i) { return i < limit; });
In C++14, you could use return type deduction to make a factory fuction :
template <class Comp>
auto predicate(typename Comp::second_argument_type rhs) {
return [c = Comp{}, rhs](typename Comp::first_argument_type lhs) {
return c(lhs, rhs);
};
}
Example call : predicate<std::less<int>>(4) returns the function object.
Live on Coliru
#Quentins answer can also be made compilable in C++11 using std::function as the return type which the lambdas are convertible to:
template <class Comp>
std::function<typename Comp::result_type (typename Comp::first_argument_type)> predicate(typename Comp::second_argument_type rhs)
{
return [rhs](typename Comp::first_argument_type lhs){
Comp c{};
return c(lhs, rhs);
};
}
live on coliru
I want to write a function that accepts a collection of type T, say std::vector<T>, but that does two different things depending on T. For example, if T is == comparable, then use a == b, else if T has a .value element, use that (a.value == b.value).
My first attempt was to use an overloaded function, but that fails if I pass in a derived class (subclass) of T.
Suppose, for example, I want to create an Exists method. (I know this can be implemented using std::find_if; it is an example only.) The following fails to compile:
using namespace std;
struct Base {
Base(string s) : value(std::move(s)) {}
string value;
};
struct Derived : public Base {
Derived(string s) : Base(std::move(s)) {}
};
bool Exists(const vector<string>& collection, const string& item) {
for (const auto& x : collection)
if (x == item)
return true;
return false;
}
bool Exists(const vector<Base>& collection, const Base& item) {
for (const auto& x : collection)
if (x.value == item.value)
return true;
return false;
}
This works fine for exact matches, such as:
Exists(vector<string>{"a", "b", "c"}, "b");
Exists(vector<Base>{{"a"}, {"b"}, {"c"}}, Base{"b"});
But it fails for derived classes:
Exists(vector<Derived>{{"a"}, {"b"}, {"c"}}, Derived{"b"})
The error is:
foo.cc:35:13: error: no matching function for call to 'Exists'
foo.cc:23:6: note: candidate function not viable: no known conversion from 'vector<Derived>' to 'const vector<Base>' for
1st argument
How can I solve this? I am interested in multiple answers, since each solution probably has pros and cons.
This is probably not a duplicate per se, but very close to this:
Is it possible to write a template to check for a function's existence?
My recommended approach is the more general solution implemented in that answer: use SFINAE.
The snippet of how to test for a member function is below (adapted from here):
template <class T>
class has_value {
template <class M>
static inline bool try_match(decltype(&M::value)) { }
template <class M>
static inline int try_match(...) { }
public:
static constexpr bool value =
sizeof(try_match<T>(nullptr)) == sizeof(bool);
};
this can then be combined with std::enable_if to solve your problem. I have posted a full solution as a GitHub gist.
In my opinion, this is superior to using base and inheritance checks as it works by simply checking (at compile-time) whether a given type has a given member. Additionally, it works for anything that has a type, meaning members, functions, static members / functions, types, etc.
One solution is to template the Exists() method and then have an overloaded comparison function. This only works if the type-specific code can be isolated. For example:
bool Equals(const string& a, const string& b) { return a == b; }
bool Equals(const Base& a, const Base& b) { return a.value == b.value; }
template <typename T>
bool Exists(const vector<T>& collection,
const typename vector<T>::value_type& item) {
for (const auto& x : collection)
if (Equals(x, item))
return true;
return false;
}
Pro: Probably the simplest solution.
Con: Does not work if you need to do some sort of expensive work up front. For example, if you need to call x.SomeExpensiveMethod() and you want to cache it for the item argument, this will not work.
Note that you need to use vector<t>::value_type and not just T in the argument or else you may get an error such as:
foo3.cc:30:13: error: no matching function for call to 'Exists'
cout << Exists(vector<string>{"a", "b", "c"}, "b") << endl;
^~~~~~
foo3.cc:21:6: note: candidate template ignored: deduced conflicting types for parameter 'T' ('std::basic_string<char>' vs.
'char [2]')
One solution is to use std::enable_if and std::is_base_of. For example:
template <typename T>
typename std::enable_if<std::is_base_of<Base, T>::value, bool>::type
Exists(const vector<T>& collection,
const typename vector<T>::value_type& item) {
const auto& item_cached = item.SomeExpensiveFunction();
for (const auto& x : collection)
if (x.SomeExpensiveFunction() == item_cached)
return true;
return false;
}
template <typename T>
typename std::enable_if<!std::is_base_of<Base, T>::value, bool>::type
Exists(const vector<T>& collection,
const typename vector<T>::value_type& item) {
for (const auto& x : collection)
if (x == item)
return true;
return false;
}
Pro: Much more general than overloading the Equals() function as described in another answer. In particular, the entire Exists() method can be customized per type.
Con: Much uglier, more complicated code.
I've this class with a map attribute which values are boost::variant.
typedef boost::variant<char, int, bool, unsigned short, float, timeval, double > MultiType;
class A {
public:
template<class T>
T& operator[](const std::string& key) {
return boost::get<T>(map_[key]);
}
template<class T>
std::string keyTypeToString(const std::string& key) {
std::stringstream ss;
ss << boost::get<T>(map_[key]);
return ss.str();
}
private:
std::map<std::string, MultiType> map_;
};
From main:
A a;
a["param"];
Compiler report this errors:
../src/main.cpp:8:25: error: no match for ‘operator[]’ in ‘a["param"]’
../src/main.cpp:8:25: note: candidate is:
../src/util/A.h:53:5: note: template T& A::operator[](const string&)
Maybe I'm missing something trivial, but I can't understand where I'm wrong..
Start with this:
template<class T>
T& get(const std::string& key) {
return boost::get<T>(map_[key]);
}
You call this like a.get<int>("hello"), where it will get the element "hello" as an int.
Next, write this:
struct pseudo_ref {
std::string const& str;
A* a;
template<typename T>
operator T&()&&{
return a->get<T>(str);
}
template<typename T>
pseudo_ref operator=( T&& t ) && {
a->get<typename std::decay<T>::type>(str) = std::forward<T>(t);
return {str, a};
}
pseudo_ref(pseudo_ref const&)=delete;
pseudo_ref& operator=(pseudo_ref const&)=delete;
pseudo_ref( std::string const& s, A* a_ ):str(s), a(a_) {}
};
then back in A:
pseudo_ref operator[](std::string const& str) {
return {str, this};
}
and we get [] that magically converts for you, so long as you assign to it/read from it using the exactly correct type.
This is somewhat dangerous, but cool.
If you want a const pseudo_ref, you need another class to represent it (with no = and operator T const& instead of operator T&).
In practice, this kind of malarkey is rarely worth it.
I wrote this in C++11, because writing it in C++03 is slightly more painful (and runs into lifetime issues with pseudo_ref -- they still exist if you have an auto&& x = a["hello"]), and less pain is good.
class A {
public:
class proxy {
friend class A;
private:
MultiType& it;
proxy(MultiType& it): it(it) {}
public:
template<typename T>
operator T&() {
return boost::get<T>(it);
}
};
proxy operator[](const std::string& key) {
return proxy(map_[key]);
}
private:
std::map<std::string, MultiType> map_;
};
EXPLANATION:
I can see that Yakk was trying similar thing. I have encapsulated the MultiType& from map_[key] in the proxy and then left the work on conversion (type-cast) operator. That's all.
Simple a[""] without assignment gets you the proxy.
double d = a["double"] will try to convert the proxy to double and thus call proxy::operator double&() (I had to test it because I was not sure if the type deduction will work as it is or will need some more work - well, it works!)
AFTERNOTE: It was not clear from the question and code provided what operations are allowed. We can modify the proxy to allow other operations or make it more readonly by changing the signature of type-conversion operator to return const T& instead.
Allowing modification leads to question: why not using MultiType& directly? (returning it from A::operator[]) And that leads to question: why class A at all?
AFTERNOTE #2: boost::variant does not have type-conversion operator and there must have been a reason for it. Think about this code:
int i = a["double"]
Runtime exception! I think that best solution would be to sub-class the MultiType and define type-conversion operator there (while checking boost::variant::which()).
ASSIGNING TO ALREADY PRESENT NAMES:
class A { ...
class proxy { ...
template<class T> proxy& operator=(const T& rhs) {
it = rhs; return *this; }
...but the above can only work if we already have some value in the map.
class A { ...
A() { map_["pi"] = 3.14; } ...
a["pi"] = 3.1415;
COMPLETE REDISIGN:
class MultiType: public boost::variant<int, double, ...> {
public:
template<class T> operator T() {
switch(which()) {
case 0: return boost::get<int>(*this);
case 1: return boost::get<double>(*this);
...
Now we can use std::map<std::string, MultiType> directly (without class A or any proxy).
template<class T>
T& operator[](const std::string& key) {
return boost::get<T>(map_[key]);
}
There's no way for the compiler to deduce T from a call like a["param"];. You'd need to specify it explicitly
a.operator[]<int>("param");
which I doubt is what you're after, but what do I know.