Variadic template constructor and empty constructor? - c++

I have a class like the following:
template<typename ... TTypes>
class Composite {
public:
//Composite() : null(true) { }
Composite(TTypes... values) : values(std::make_tuple(values...)), null(false) { }
private:
bool null;
std::tuple<TTypes...> values;
};
int main(int argc, char *argv[]) {
Composite<int, char, int> a1;
}
But this leads to an error because the second constructor would override the first one with TTypes = {}. Is there any way to keep the empty constructor?
Best,
Moritz

Since none of the existing answers so actually solve the problem, but there is a solution by Piotr Skotnicki hidden in the comments, I'm just gonna repost it here for visibility:
#include <tuple>
#include <type_traits>
template<typename ... TTypes>
class Composite {
public:
Composite() : null(true) { }
template <std::size_t N = sizeof...(TTypes), typename std::enable_if<(N>0), int>::type = 0>
Composite(TTypes... values) : values(std::make_tuple(values...)), null(false) { }
private:
bool null;
std::tuple<TTypes...> values;
};
int main(int argc, char *argv[]) {
Composite<int, char, int> a1;
Composite<> a2;
}

I am not sure whether the following work around is an option for you:
template<typename ... TTypes>
class Composite : public ValueSet {
public:
Composite(TTypes... values) { }
};
template<>
class Composite<> : public ValueSet {
public:
Composite() : ValueSet() { }
};
but it works.

The case where your parameter pack TTypes is empty makes the default constructor ambiguous. If you plan to provide at least 1 parameter, then you can specify an additional parameter:
template<typename TType, typename ... TTypes>
class Composite {
public:
Composite() : null(true) { }
Composite(TType first, TTypes... rest) :
values(std::make_tuple(first,rest...)),
null(false)
{
}
private:
bool null;
std::tuple<TType,TTypes...> values;
};
int main(int argc, char *argv[]) {
Composite<int, char, int> a1;
}
However, take into account that this functionality is provided by std::optional, so it should be better using it.
template < typename... TTypes >
using Composite = std::optional<std::tuple<TTypes...>>;

Related

C++ - "unspecialized class template" in unordered_map with shared_ptr to template class

I have a class UISceneParams and I use it to store some parameters that I want to send over to a UIScene. It contains a unordered_map of shared_ptrs to DataParam instances.
The problem is that my DataParam must use a template and feature multiple data types.
Is there any way I can make the unordered_map use multiple data types of DataParams?
I currently call this like this:
UISceneParams p;
p.AddParam<int>("test_value", 123);
p.AddParam<int>("test_value2", 456);
and in my scene I get the parameters using the GetParam<T> method, like this:
int value1 = p.GetParam<int>("test_value", 0);
int value2 = p.GetParam<int>("test_value2", 0);
I've been trying many ways to circumvent the errors, but I am a beginner with templates in C++. Can someone get me on the right track?
UISceneParams.h
#pragma once
#include <string>
#include <unordered_map>
#include <memory>
using namespace std;
template <typename T>
class DataParam {
public:
DataParam(string t, T v) {
_tag = t;
_val = v;
}
T Value() const {
return _val;
}
string Tag() const {
return _tag;
}
private:
string _tag;
T _val;
};
class UISceneParams {
public:
bool HasParam(string tag) {
return params.find(tag) != params.end();
}
template <typename T>
void AddParam(string tag, T value) {
if (HasParam(tag)) params.erase(tag);
params.insert({ tag, make_shared<DataParam>(tag, value) });
}
template <typename T>
T GetParam(string tag, T def_value) {
if (!HasParam(tag)) return def_value;
auto p = params.find(tag)->second;
return p->Value;
}
private:
unordered_map<string, shared_ptr<DataParam>> params;
};
Edit: Final code
#pragma once
#include <string>
#include <unordered_map>
#include <memory>
using namespace std;
class IDataParam
{
public:
virtual ~IDataParam() = default;
};
template <typename T>
class DataParam : public IDataParam {
public:
DataParam(string t, T v) {
_tag = t;
_val = v;
}
T Value() const {
return _val;
}
string Tag() const {
return _tag;
}
private:
string _tag;
T _val;
};
class UISceneParams {
public:
bool HasParam(string tag) {
return params.find(tag.data()) != params.end();
}
template <typename T>
void AddParam(string tag, T value) {
if (HasParam(tag)) params.erase(tag);
params.insert({ tag, make_shared<DataParam<T>>(tag, value) });
}
template <typename T>
T GetParam(string tag, T def_value) {
if (!HasParam(tag)) return def_value;
auto p = dynamic_cast<const DataParam<T> &>(*params.find(tag)->second);
return p.Value();
}
private:
unordered_map<string, shared_ptr<IDataParam>> params;
};
You could make your DataParam inherit from a marker interface like IDataParam, where the interface is just like
class IDataParam
{
virtual ~IDataParam() = default;
};
You could then store all your params as unordered_map<string, shared_ptr<IDataParam>> since they all have the same base type.
Then when getting the param, you just get the IDataParam first by the string key. And then you do a static_cast<const DataParam<T> &>(*gotParam) for example to cast it down to the correct templated DataParam type before returning.
Of course this would not work if you have multiple params with the same key but different T, of you might also run into trouble if you get a param as a type that it is not, to circumvent this issue you could use dynamic_cast though

Which pattern to generify instantiation of objects that have different Ctor arguments

I would like to construct a robot with or without a tool, a mobile base, and other parts. As I want to automatize the configuration of the parts, I have a class Robot with the parts as template arguments
For instance, in the code below, the code will build as long as we use tools that have the same constructor signature as ToolInterface. It does build with a Screwdriver but does not with a Gripper.
#include <iostream>
#include <string>
class BaseRobot
{
public:
BaseRobot(){};
};
class ToolInterface
{
public:
ToolInterface(BaseRobot* _base, std::string _name):name{_name}{/*register _base*/};
std::string name;
bool param_1;
char param_2;
};
template<class T, class... Args>
constexpr T* construct(Args... args)
{
if constexpr (std::is_same<T, nullptr_t>::value)
{
return nullptr;
}
else
{
return new T(args...);
}
};
template<class Tool>
class Robot : public BaseRobot
{
protected:
Tool* tool;
public:
Robot():tool(construct<Tool>(this, "tool")){ // <--- here is my problem !!
if constexpr (! std::is_same<Tool, nullptr_t>::value)
{
//do stuff on/with tool->param_1, tool->param_2, ...
std::cout << "tool configured" << std::endl;
}
else
std::cout << "no tool" << std::endl;
};
};
class Screwdriver: public ToolInterface
{
public:
Screwdriver(BaseRobot* _base, std::string _name):ToolInterface(_base, _name){};
};
class Gripper: public ToolInterface
{
public:
Gripper(BaseRobot* _base, std::string _name, bool _reversed):
ToolInterface(_base, _name)
,reversed{_reversed}{};
bool reversed;
};
int main()
{
Robot<Screwdriver> robot_screwdriver;
Robot<nullptr_t> robot_null;
//Robot<Gripper> robot_gripper; //does not build
return 0;
}
Here are some ideas :
using a ToolConfig struct that is passed as an argument of Tools. If a tool requires more arguments, one should subclass ToolConfig and cast it into the tool constructor (see below): damn, that looks cumbersome and ugly!
enforce inherited ToolInterface classes Ctor signature: some tools must have a different Ctor signature
using a variadic template to pass args into the template: not reasonable because, in the end, I want something like template<class Tool1, class Tool2, class MobileBase, class Camera> class Robot
solution 1 would look like
struct ToolConfig
{
std::string name;
};
struct GripperConfig : public ToolConfig
{
bool reversed;
};
class Gripper : public ToolInterface
{
public:
Gripper(ToolConfig& _config):
ToolInterface(_config)
,reversed{static_cast<GripperConfig&>(_config).reversed}{};
bool reversed;
};
Do you have a magic pattern to solve my problem? Is my pattern wrong?
You could also use tuple instead of struct, not ideal but this works as well:
#include <iostream>
#include <string>
#include <tuple>
class BaseRobot
{
public:
BaseRobot() {};
};
class ToolInterface
{
public:
ToolInterface(std::string _name) :name{ _name } {/*register _base*/ };
std::string name;
bool param_1;
char param_2;
};
template <typename T, typename ... Types, std::size_t ... Indices>
constexpr T* apply_impl(const std::tuple<Types...>& tuple, std::index_sequence<Indices...>)
{
return new T(std::get<Indices>(tuple)...);
}
template <typename T, typename ... Types>
constexpr T* apply(const std::tuple<Types...>& tuple)
{
return apply_impl<T>(tuple, std::index_sequence_for<Types...>());
}
template<class T, class... Args>
constexpr T* construct(std::tuple<Args...> args)
{
if constexpr (std::is_same<T, nullptr_t>::value)
{
return nullptr;
}
else
{
return apply<T>(args);
}
}
template<class Tool>
class Robot : public BaseRobot
{
protected:
Tool* tool;
public:
template<class ...Args1> //, class ...Args2>
Robot(std::tuple<Args1...> p1): // , std::tuple<Args2...> p2):
tool(construct<Tool>(p1))
{ // <--- here is my problem !!
if constexpr (!std::is_same<Tool, nullptr_t>::value)
{
//do stuff on/with tool->param_1, tool->param_2, ...
std::cout << "tool configured" << std::endl;
}
else
std::cout << "no tool" << std::endl;
};
};
class Screwdriver : public ToolInterface
{
public:
Screwdriver(std::string _name) :ToolInterface(_name) {};
};
class Gripper : public ToolInterface
{
public:
Gripper(std::string _name, bool _reversed) :
ToolInterface(_name)
, reversed{ _reversed }{};
bool reversed;
};
int main()
{
using p1 = std::tuple<std::string>;
Robot<Screwdriver> robot_screwdriver(p1{"sdvr"});
return 0;
}
Could be improved I agree.
You could pass factory lambdas that generate your tools in the initializer.
template<typename Func>
Robot(Func f):tool(f(this, "tool")){ // <--- here is my problem !!
if constexpr (! std::is_same<Tool, std::nullptr_t>::value)
{
//do stuff on/with tool->param_1, tool->param_2, ...
std::cout << "tool configured" << std::endl;
}
else
std::cout << "no tool" << std::endl;
};
The call site would look like this:
Robot<Screwdriver> robot_screwdriver([](auto... args){ return new Screwdriver(args...); });
Robot<std::nullptr_t> robot_null([](auto...){ return nullptr; });
Robot<Gripper> robot_gripper([](auto... args){ return new Gripper(args..., true); });
Not exactly beautiful, but it works.
See here for a full example. Does this solve your problem?
If you can use c++17, you can add a class template deduction guide to reduce some of the redundancy at the call site.

Command line arguments for different constructors

Let's suppose I have some C++ abstract class and all its inherited classes have different constructors:
class Abstract{
//don't worry, there is some pure virtual method here
}
class A : public Abstract {
public:
A (int Afirst, std::string Asecond, int Athird) {...}
...
}
class B : public Abstract {
public
B (double Bfirst, std::int Bsecond) {...}
...
}
class C : public Abstract {
public
C (std::string Cfirst, double Csecond, int Cthird, float Cfourth) {...}
}
As you can see, all the inherited class have (possibly) different constructors.
Now, I want to write a generic main(), something like:
int main (int argc, char *argv[]){
if(argc < 2){
std::cerr<<"Too few arguments!"<<std::endl;
exit(1);
}
std::string type = argv[1];
Abstract *abs;
if(!type.compare("A"){
if(argc < 5){
std::cerr<<"Too few arguments for A!"<<std::endl;
exit(1);
}
abs = new A(atoi(argv[2]), argv[3], argv[4]);
}
//similar for B, C, D
}
I wonder if there is a best way to do this, for example passing directly char *argv[] to each constructor and make all the checks inside the constructor (and eventually throwing an exception as described here).
You may do something like that to be generic:
// functions to convert const char* to given type
template <typename T> T To(const char*);
template <> int To(const char* s) { return atoi(s); }
template <> const char* To(const char* s) { return s; }
template <> std::string To(const char* s) { return s; }
// ...
// Your classes:
struct Abstract { virtual ~Abstract() = default; };
struct A : Abstract { A (int, std::string, int) {}};
struct B : Abstract { B (int, int) {}};
// ...
namespace detail
{
// Helper functions for the factory.
template <typename T, typename Tuple, std::size_t... Is>
std::unique_ptr<Abstract> make_abstract(const char*argv[], std::index_sequence<Is...>)
{
return std::make_unique<T>(To<std::tuple_element_t<Is, Tuple>>(argv[2 + Is])...);
}
template <typename T, typename Tuple>
std::unique_ptr<Abstract> make_abstract(int argc, const char*argv[])
{
constexpr int tuple_size = std::tuple_size<Tuple>::value;
if (argc < tuple_size) {
throw std::runtime_error("Too few arguments");
}
return make_abstract<T, Tuple>(argv, std::make_index_sequence<tuple_size>());
}
}
// The public factory
std::unique_ptr<Abstract> make_abstract(int argc, const char*argv[])
{
if (argc == 1) {
return nullptr;
}
const std::string name = argv[1];
if (name == "A") {
return detail::make_abstract<A, std::tuple<int, std::string, int>>(argc, argv);
} else if (name == "B") {
return detail::make_abstract<B, std::tuple<int, int>>(argc, argv);
}
// ...
return nullptr;
}

How to implement a discriminated union of a parameterless functor and its return value in C++?

I know I could use boost::variant and avoid having to ask this question. But using boost::variant involves a lot of ugly code. In particular, visitors are messy. So, without further ado...
I have written the following templated class to implement lazy evaluation of curried functions. (See my previous question for the whole snippet.)
template <typename> class curry;
template <typename _Res>
class curry< _Res() >
{
public:
typedef std::function< _Res() > _Fun;
typedef _Res _Ret;
private:
_Fun _fun;
public:
explicit curry (_Fun fun)
: _fun(fun) { }
operator _Ret ()
{ return _fun(); }
};
So I want to update it to include memoization. Conceptually, it is very simple. First of all, I have to replace:
private:
_Fun _fun;
public:
explicit curry (_Fun fun)
: _fun(fun) { }
With:
private:
bool _evaluated; // Already evaluated?
union
{
_Fun _fun; // No
_Res _res; // Yes
};
public:
explicit curry (_Fun fun)
: _evaluated(false), _fun(fun) { }
explicit curry (_Res res)
: _evaluated(true), _res(res) { }
But there are two things left. First, I have to update operator _Ret so that, if it performs the lazy evaluation, then the result actually gets memoized. Second, I have to add a destructor so that, depending on the value of _evaluated, either _fun or _res gets destroyed. And here is where I am not quite sure about how to do things.
First, is this the correct way to replace _fun with _res? If not, how should I do it?
operator _Ret ()
{
if (!_evaluated) {
_Fun fun = _fun;
// Critical two lines.
_fun.~_Fun();
_res._Res(fun());
_evaluated = true;
}
return _res;
}
Second, is this the correct way to selectively destroy _fun or _res? If not, how should I do it?
~curry ()
{
if (_evaluated)
_res.~_Res();
else
_fun.~_Fun();
}
You can't use a union as the other commenters have stated, but you can use placement new.
Here's an example of a discriminated union using placement new:
Note that there may be alignment restrictions on your platform for the A and B types, and enforcing those restrictions is not handled by this code.
#include <iostream>
#include <cstring>
using namespace std;
struct foo {
foo(char val) : c(val) {
cout<<"Constructed foo with c: "<<c<<endl;
}
~foo() {
cout<<"Destructed foo with c: "<<c<<endl;
}
char c;
};
struct bar {
bar(int val) : i(val) {
cout<<"Constructed bar with i: "<<i<<endl;
}
~bar() {
cout<<"Destructed bar with i: "<<i<<endl;
}
int i;
};
template < size_t val1, size_t val2 >
struct static_sizet_max
{
static const size_t value
= ( val1 > val2) ? val1 : val2 ;
};
template <typename A, typename B>
struct unionType {
unionType(const A &a) : isA(true)
{
new(bytes) A(a);
}
unionType(const B &b) : isA(false)
{
new(bytes) B(b);
}
~unionType()
{
if(isA)
reinterpret_cast<A*>(bytes)->~A();
else
reinterpret_cast<B*>(bytes)->~B();
}
bool isA;
char bytes[static_sizet_max<sizeof(A), sizeof(B)>::value];
};
int main(int argc, char** argv)
{
typedef unionType<foo, bar> FooOrBar;
foo f('a');
bar b(-1);
FooOrBar uf(f);
FooOrBar ub(b);
cout<<"Size of foo: "<<sizeof(foo)<<endl;
cout<<"Size of bar: "<<sizeof(bar)<<endl;
cout<<"Size of bool: "<<sizeof(bool)<<endl;
cout<<"Size of union: "<<sizeof(FooOrBar)<<endl;
}

Variadic templates - is there a way to avoid repetition

In code (just paste and copy)is there a way to avoid repetition/listing of template args(line marked in code):
#include <iostream>
using namespace std;
template<class T,class... V>
struct nullptr_
{
nullptr_(T& obj,V&... args)
{
nullptr_hlp(obj,args...);
}
template<class A>
static void nullptr_hlp(A& a);
{
a = nullptr;
}
template<class A,class... Vs>
static void nullptr_hlp(A& a,Vs&... args)
{
a = nullptr;
nullptr_hlp(args...);
}
};
class X : nullptr_<int*,double*,char*>//IS THERE A WAY TO HAVE JUST nullptr_?
{
int* a;
double* b;
char* c;
typedef nullptr_<decltype(a),decltype(b),decltype(c)> init_;
public:
X():init_(a,b,c)
{
}
};
int main()
{
X x;
return 0;
}
nullptr_<int*,double*,char*> becomes an injected class name within X, so you can refer to it without the argument list:
class X : nullptr_<int*,double*,char*>//can't do away with the list here, unless you want to typedef it
{
int* a;
double* b;
char* c;
//typedef nullptr_<decltype(a),decltype(b),decltype(c)> init_; //don't really need this
public:
X():nullptr_(a,b,c) //can be used without the argument list
{
}
};
How about moving the typedef out of the class in to an anonymous namespace and use that for inheritance?