C++20 introduced many improvements like requires, concepts, constraints, modules and much more - functionality you really miss in C++17.
How can a scenario having conditional constructors be implemented in C++17, that could look like the following C++20 example (using requires)?
template <typename T> concept has_type = requires { typename T::type; };
template <typename T>
class someClass {
public:
using data_t = typename std::conditional_t<has_type<T>, T, std::type_identity<T> >::type;
constexpr someClass(T const& _a, T const& _b) requires std::is_arithmetic_v<T> : a{_a}, b{_b} {}
constexpr someClass(data_t const& _a, data_t const& _b,) requires has_type<T> : a{_a}, b{_b} {}
private:
const data_t a, b;
};
One constructor has to be used in case of T is an arithmetic type (int, float, double, ...).
Another constructor needs to catch the case of T being a class/struct having a nested type alias (e.g. struct x { using type=float; };).
Using SFINAE
template <typename, typename = std::void_t<>>
struct HasTypeT : std::false_type {};
template <typename T>
struct HasTypeT<T, std::void_t<typename T::type>> : std::true_type {};
template <typename T>
struct type_identity {
using type = T;
};
template <typename T>
class someClass {
public:
using data_t = typename std::conditional_t<HasTypeT<T>::value, T, type_identity<T> >::type;
template <typename U = T, typename = std::enable_if_t<std::is_arithmetic_v<U>>>
constexpr someClass(T const& _a, T const& _b) : a{_a}, b{_b} {}
template <typename U = T, typename = std::enable_if_t<HasTypeT<U>::value>>
constexpr someClass(typename U::type const& _a, typename U::type const& _b) : a{_a}, b{_b} {}
private:
const data_t a, b;
};
Demo
Related
I have a templated class MyClass<T> that takes some iterable containing ints (e.g. T = std::vector<int>) in its constructor and does something with it.
I would like to be able to pass the iterable as either a temporary object (e.g. MyClass(std::vector<int>{3,6,9}) or similar r-value argument) or from a named variable (resulting in an l-value as the constructor argument).
I would like to use C++17 template class inference (i.e. write MyClass(...), not MyClass<std::vector<int>>(...)).
I thought that I could declare the constructor parameter as MyClass(T && vec) (a "universal reference") to take either an l-value or an r-value (just like I can with functions), but it gives an error. It seems like T is always inferred as std::vector<int> and never std::vector<int>& with classes, whereas functions infer std::vector<int>& when the argument is an l-value.
How exactly are the rules for template constructor inference and template function inference different? Can I avoid having to use a wrapper function (e.g. myFunction(T&&vec) { return MyClass<T>(std::forward<T>(vec)); }) just for the sake of template inference?
Run the code below on Godbolt:
#include <iostream>
#include <utility>
#include <vector>
template <typename T>
using BeginType = decltype(std::declval<T>().begin());
template <typename T>
struct MyClass {
BeginType<T> begin;
BeginType<T> end;
MyClass(T && vec) {
begin = std::forward<T>(vec).begin();
end = std::forward<T>(vec).end();
}
int sum() {
int sum = 0;
for (auto it = begin; it != end; ++it) sum += *it;
return sum;
}
};
template <typename T>
MyClass<T> myFunction(T && vec) {
return MyClass<T>(std::forward<T>(vec));
}
int main() {
std::vector<int> x{1, 2, 3};
std::vector<int> y{2, 4, 6};
// Warmup: Passing r-values works fine
std::cout << MyClass(std::vector<int>{3, 6, 9}).sum() << std::endl; // works fine: T is std::vector<int>
std::cout << MyClass(std::move(y)).sum() << std::endl; // works fine: T is std::vector<int>
// Unexpected: Passing l-values doesn't work
// std::cout << MyClass(x).sum() << std::endl; // error: cannot bind rvalue reference of type 'std::vector<int>&&' to lvalue of type 'std::vector<int>'
// Compare: Passing l-values to function works fine
std::cout << myFunction(x).sum() << std::endl; // works fine: T is std::vector<int>&
}
Add a user-defined deduction guide after the class definition:
template <typename T>
struct MyClass {
// same as in question
};
template <typename TT> MyClass(TT && vec) -> MyClass<TT>;
See also How to write a constructor for a template class using universal reference arguments in C++
I can't seem to figure out how to get the following to compile.
I am trying to write a binary operator which:
Is defined in a separate compilation unit (file)
Lives in a nested namespace
Here's some code:
// header.h
namespace ns1
{
namespace ns2
{
class myClass
{
friend bool operator==(const myClass& l, const myClass& r);
protected:
int a;
};
}
}
// header.cpp
#include "header.h"
using namespace ns1;
using namespace ns1::ns2;
bool operator==(const myClass& l, const myClass& r)
{
if(l.a != r.a) return false;
return true;
}
// main.cpp
#include "header.h"
using namespace ns1::ns2;
using namespace std;
int main()
{
myClass class1;
myClass class2;
if(class1 == class2)
{
cout << "hello world" << endl;
}
return 0;
}
This is the output from the compiler:
In function ‘bool operator==(const ns1::ns2::myClass&, const ns1::ns2::myClass&)’:
error: ‘int ns1::ns2::myClass::a’ is protected within this context
I have a suspicion that this is related to the compiler not understanding which namespace operator== should be in. I have tried explicitly declaring this, but that didn't help either.
The question is what is going on here? What is the compiler thinking?
Edit
Note: I posted this edit in response to an answer which was then deleted. The suggestion was to put the operator inside ns1::ns2, however this did not work. See the below output.
New compiler output:
error: ‘bool ns1::ns2::operator==(const ns1::ns2::myClass&, const ns1::ns2::myClass&)’ has not been declared within ‘ns1::ns2’ [-Werror]
bool ns1::ns2::operator==(const myClass& l, const myClass& r)
note: only here as a ‘friend’
friend bool operator==(const myClass& l, const myClass& r);
The problem here is when you declare a friend function inside your class, this function belongs to the innermost enclosing namespace, you have to define
bool ns1::ns2::operator==(const myClass& l, const myClass& r)
It should be defined inside namespace ns1::ns2 but not just introduced it with using directives,
// header.cpp
#include "header.h"
namespace ns1 {
namespace ns2 {
bool operator==(const myClass& l, const myClass& r)
{
if(l.a != r.a) return false;
return true;
}
}
}
Demo
or
// header.h
namespace ns1
{
namespace ns2
{
class myClass
{
...
};
bool operator==(const myClass& l, const myClass& r);
}
}
// header.cpp
bool ns1::ns2::operator==(const myClass& l, const myClass& r)
Demo
Another way is to declare your friend function as a global one,
// header.h
#pragma once
namespace ns1
{
namespace ns2
{
class myClass;
}
}
bool operator==(const ns1::ns2::myClass& l, const ns1::ns2::myClass& r);
namespace ns1
{
namespace ns2
{
class myClass
{
friend bool ::operator==(const myClass& l, const myClass& r);
protected:
int a;
};
}
}
// header.cpp
#include "header.h"
using namespace ns1::ns2;
bool operator==(const myClass& l, const myClass& r)
{
if(l.a != r.a) return false;
return true;
}
Demo
I am trying to convert the following pydrake code to C++ version. Unfortunately,I get lost in the very rigorous C++ API documentation. Could you help to convert the following code into C++ version for a tutorial? Thank you so much!
import pydrake.math as drake_math
import pydrake.symbolic as sym
def cost_stage(x):
m = sym if x.dtype == object else np # Check type for autodiff
cost = m.sqrt(x[0]**2 + x[1]**2 )
return cost
x_sym = np.array([sym.Variable("x_{}".format(i)) for i in range(n_x)])
x = x_sym
l = cost_stage(x)
self.l_x = sym.Jacobian([l], x).ravel()
Since you used the name "cost", I suppose you want to use this as a cost in drake's MathematicalProgram, so I created MyCost class which can be used in Drake's MathematicalProgram. If you don't want to use MathematicalProgram later, you could just use the templated function DoEvalGeneric only without the class MyCost.
Here is the C++ pseudo-code (I didn't compile or run the code, so it is highly likely there are bugs in the code, but you get the idea)
#include "drake/solvers/cost.h"
#include "drake/common/symbolic.h"
class MyCost : public drake::solvers::Cost {
public:
MyCost() {}
protected:
void DoEval(const Eigen::Ref<const Eigen::VectorXd>& x, Eigen::VectorXd* y) const override {
DoEvalGeneric<double>(x, y);
}
void DoEval(const Eigen::Ref<const drake::AutoDiffVecXd>& x, drake::AutoDiffVecXd* y) const override {
DoEvalGeneric<drake::AutoDiffXd>(x, y)
}
void DoEval(const Eigen::Ref<const drake::VectorX<drake::symbolic::Variable>>& x, drake::VectorX<drake::symbolic::Expression>* y) const override {
DoEvalGeneric<drake::symbolic::Expression>(x.cast<drake::symbolic::Expression>(), y);
}
private:
template <typename T>
void DoEvalGeneric(const Eigen::Ref<const drake::VectorX<T>>& x, drake::VectorX<T>* y) const {
y->resize(1);
using std::sqrt
(*y)(0) = sqrt(x[0] * x[0] + x[1] * x[1]);
}
};
void main() {
const drake::symbolic::Variable x0{"x0"};
const drake::symbolic::Variable x1{"x1"};
drake::Vector2<drake::symbolic::Variable> x(x0, x1);
MyCost cost{};
drake::VectorX<drake::symbolic::Expression> y;
cost.Eval(x, &y);
std::cout << y(0).Jacobian(x) << "\n";
}
Here I created a templated function DoEvalGeneirc to handle the three different scalar types double, AutoDiffXd and symbolic expression. You could see similar patterns in the drake codebase https://github.com/RobotLocomotion/drake/blob/6ee5e9325821277a62bd5cd5456ccf02ca25dab7/solvers/cost.cc#L14-L33
If you don't need to use cost in drake MathematicalProgram, then you can create your cost function in C++ as
#include "drake/common/symbolic.h"
#include <Eigen/Core>
template <typename Derived>
typename Derived::Scalar cost_stage(const Derived& x) {
using std::sqrt;
return sqrt(x[0] * x[0] + x[1] * x[1]);
}
int main() {
const drake::symbolic::Variable x0{"x0"};
const drake::symbolic::Variable x1{"x1"};
drake::Vector2<drake::symbolic::Variable> x(x0, x1);
const drake::symbolic::Expression l = cost_stage(x.cast<drake::symbolic::Expression>());
std::cout << l.Jacobian(x) << "\n";
return 0;
}
Then you can call Jacobian on the return argument of cost_stage.
There is a class template:
template<std::size_t ID, std::size_t T1, std::size_t T2, std::size_t T3>
class Feature { /* Implementation goes here */ };
All the instantiations of Feature<...> are 'collected' here:
template<typename FEATURE, typename... OTHERS>
class Features<FEATURE, OTHERS...> : public Features<OTHERS...> {
public:
/* Operations defined here */
private:
FEATURE m_feature;
};
All the features are created as follows:
using FeatureConfig = Features<Feature<0, 1, 2, 3>, Feature<1, 4, 5, 6>>;
FeatureConfig m_features;
So far so good. My task is to get rid of those hard coded values in there 1..3, 4..6 etc. The way to do so is to have generated header file which contains the configuration for all the features. Something like:
template<std::size_t> struct Config;
template<>
struct Config<0> {
static constexpr std::size_t t1 { 1 };
static constexpr std::size_t t2 { 2 };
static constexpr std::size_t t3 { 3 };
};
template<>
struct Config<1> {
static constexpr std::size_t t1 { 4 };
static constexpr std::size_t t2 { 5 };
static constexpr std::size_t t3 { 6 };
};
Then I need to change type definition of FeatureConfig somehow to use the specializations of FeatureConfig based on an index (0, 1, ...). My unsuccessfull try is:
template<std::size_t... INDEX_SEQUENCE>
using FeatureConfig = Features<Feature<INDEX_SEQUENCE, Config<INDEX_SEQUENCE>::t1, Config<INDEX_SEQUENCE>::t2, Config<INDEX_SEQUENCE>::t3>...>;
FeatureConfig<std::make_index_sequence<2>> m_features;
It seems I am somehow mixing type and value...
Many thanks in advance to anyone willing to help me fix the incorrect code in my last listing up there.
Cheers Martin
If I understand correctly what do you want...
I propose the declaration (no definition required because is used only inside a decltype()) of the following function
template <std::size_t ... Is>
auto getFeaturesType (std::index_sequence<Is...>)
-> Features<Feature<Is, Config<Is>::t1, Config<Is>::t2, Config<Is>::t3>...>;
Now you can define FeatureConfig simply as follows
template <std::size_t N>
using FeatureConfig
= decltype(getFeaturesType(std::make_index_sequence<N>{}));
The following is a full compiling (simplified) example
#include <type_traits>
#include <utility>
template <std::size_t, std::size_t, std::size_t, std::size_t>
struct Feature { };
template <typename...>
struct Features
{ };
template <typename F, typename... Os>
struct Features<F, Os...> : public Features<Os...>
{ F m_feature; };
template <std::size_t N>
struct Config
{
static constexpr std::size_t t1 { N*3u };
static constexpr std::size_t t2 { 1u + N*3u };
static constexpr std::size_t t3 { 2u + N*3u };
};
template <std::size_t ... Is>
auto getFeaturesType (std::index_sequence<Is...>)
-> Features<Feature<Is, Config<Is>::t1, Config<Is>::t2, Config<Is>::t3>...>;
template <std::size_t N>
using FeatureConfig
= decltype(getFeaturesType(std::make_index_sequence<N>{}));
int main ()
{
using T1 = FeatureConfig<2u>;
using T2 = Features<Feature<0u, 0u, 1u, 2u>, Feature<1u, 3u, 4u, 5u>>;
static_assert( std::is_same<T1, T2>::value, "!" );
}
If I understand correctly how do you use Config (if t1 is ever N*3u, if if t2 is ever 1u+N*3u and if t3 is ever 2u+N*3u), you can avoid Config at all and write getFeaturesType as follows
template <std::size_t ... Is>
auto getFeaturesType (std::index_sequence<Is...>)
-> Features<Feature<Is, Is*3u, Is*3u+1u, Is*3u+2u>...>;
I was reading this Q/A here and as my question is similar but different I would like to know how to do the following:
Let's say I have a basic non template non inherited class called Storage.
class Storage {};
I would like for this class to have a single container (unordered multimap) is where I'm leaning towards... That will hold a std::string for a name id to a variable type T. The class itself will not be template. However a member function to add in elements would be. A member function to add might look like this:
template<T>
void addElement( const std::string& name, T& t );
This function will then populate the unorderd multimap. However each time this function is called each type could be different. So my map would look something like:
"Hotdogs", 8 // here 8 is int
"Price", 4.85f // here 4.8f is float.
How would I declare such an unorderd multimap using templates, variadic parameters, maybe even tuple, any or variant... without the class itself being a template? I prefer not to use boost or other libraries other than the standard.
I tried something like this:
class Storage {
private:
template<class T>
typedef std::unorderd_multimap<std::string, T> DataTypes;
template<class... T>
typedef std::unordered_multimap<std::vector<std::string>, std::tuple<T...>> DataTypes;
};
But I can not seem to get the typedefs correct so that I can declare them like this:
{
DataTypes mDataTypes;
}
You tagged C++17, so you could use std::any (or std::variant if the T type can be a limited and know set of types`).
To store the values is simple.
#include <any>
#include <unordered_map>
class Storage
{
private:
using DataTypes = std::unordered_multimap<std::string, std::any>;
DataTypes mDataTypes;
public:
template <typename T>
void addElement (std::string const & name, T && t)
{ mDataTypes.emplace(name, std::forward<T>(t)); }
};
int main()
{
Storage s;
s.addElement("Hotdogs", 8);
s.addElement("Price", 4.85f);
// but how extract the values ?
}
But the problem is that now you have a element with "Hotdogs" and "Price" keys in the map, but you have no info about the type of the value.
So you have to save, in some way, a info about the type of th value (transform the value in a std::pair with some id-type and the std::any?) to extract it when you need it.
I've done something along those lines, the actual solution is very specific to your problem.
That being said, I'm doing this on a vector, but the principle applies to maps, too.
If you're not building an API and hence know all classes that will be involved you could use std::variant something along the lines of this:
#include <variant>
#include <vector>
#include <iostream>
struct ex1 {};
struct ex2 {};
using storage_t = std::variant<ex1, ex2>;
struct unspecific_operation {
void operator()(ex1 arg) { std::cout << "got ex1\n";}
void operator()(ex2 arg) { std::cout << "got ex2\n";}
};
int main() {
auto storage = std::vector<storage_t>{};
storage.push_back(ex1{});
storage.push_back(ex2{});
auto op = unspecific_operation{};
for(const auto& content : storage) {
std::visit(op, content);
}
return 0;
}
which will output:
got ex1
got ex2
If I remember correctly, using std::any will enable RTTI, which can get quite expensive; might be wrong tho.
If you provide more specifics about what you actually want to do with it, I can give you a more specific solution.
for an example with the unordered map:
#include <variant>
#include <unordered_map>
#include <string>
#include <iostream>
struct ex1 {};
struct ex2 {};
using storage_t = std::variant<ex1, ex2>;
struct unspecific_operation {
void operator()(ex1 arg) { std::cout << "got ex1\n";}
void operator()(ex2 arg) { std::cout << "got ex2\n";}
};
class Storage {
private:
using map_t = std::unordered_multimap<std::string, storage_t>;
map_t data;
public:
Storage() : data{map_t{}}
{}
void addElement(std::string name, storage_t elem) {
data.insert(std::make_pair(name, elem));
}
void doSomething() {
auto op = unspecific_operation{};
for(const auto& content : data) {
std::visit(op, content.second);
}
}
};
int main() {
auto storage = Storage{};
storage.addElement("elem1", ex1{});
storage.addElement("elem2", ex2{});
storage.addElement("elem3", ex1{});
storage.doSomething();
return 0;
}