Template function in class - c++

I don't know what to do. I always get an error by using a simple class and a simple template function. I read all the other solutions but they didn't helped me.
Next to some other classes I have the simple class Data:
class Data{
public:
template <class T>
T dat();
int id;
union{
char c;
int i;
double d;
};
};
and the function dat:
template <class T>
T Data::dat(){
if(id == 1) return i;
if(id == 2) return d;
if(id == 3) return c;
}
As you can see, I want to check the id and return int, double or char.
Now I've tried to print the value in the main function like this:
Data test;
test.id=1;
test.i = 12;
cout<<test.dat();
But I always get this error message:
Error: Could not find a match for Data::dat<Data::T>() needed in main(int, char**).
Where is the problem??
Thank you

To put it precisely, you want the return type of the function to
depend on it's the id field in the object; in other words,
dynamically. Templates are resolved at compile time, so they
cannot help here. You'll have to return something like
boost::variant or boost::any, which supports such dynamic
typing.

Use this:
cout<<test.dat<int>();

dat() has no parameters involving T, so the compiler cannot deduce T from the call and it must be provided explicitly, e.g.:
cout << test.dat<int>();
Also, bear in mind you must implement dat() in the header file.

I don't know what to do. I always get an error by using a simple class and a simple template function. I read all the other solutions but they didn't helped me.
It seems to me that you want to create a discriminated union.
Your implementation won't work, because the return type of a template function is determined at compilation time (i.e. before you set a value in id and try to call the function.
Solution:
class Data
{
enum value_type {
int_val, char_val, double_val
} discriminator; // private (the user doesn't see this)
// this replaces your id
union{
char c;
int i;
double d;
} value;
public:
class wrong_type_error: public std::logic_error
{
public:
wrong_type_error(const std::string& msg): std::logic_error(msg) {}
};
explicit Data(const char c)
: discriminator(Data::char_value)
, value.c(c)
{
}
explicit Data(const int i)
: discriminator(Data::int_value)
, value.i(i)
{
}
explicit Data(const double d)
: discriminator(Data::double_value)
, value.d(d)
{
}
// don't put this here: int id;
// this part can be optimized to simpler (more idiomatic) code
template<typename T> T get() const; // undefined
template<> int get() const {
if(discriminator != Data::int_val)
throw wrong_type_error("Cannot return a int from Data instance");
return value.i;
}
template<> char get() const {
if(discriminator != Data::char_val)
throw wrong_type_error("Cannot return a char from Data instance");
return value.c;
}
template<> double get() const {
if(discriminator != Data::double_val)
throw wrong_type_error("Cannot return a double from Data instance");
return value.d;
}
};
Client code:
Data test(10.5);
cout<<test.get<double>();
All that said, you should consider using a boost::variant or boost::any instance, depending on your needs.

VS2012 says
"error C2783: 'T Data::dat(void)' : could not deduce template argument for 'T'"
You just need to tell the function dat what T is:
cout<<test.dat<int>();
The template type can be deduced if you pass a templated parameter, but it cannmot guess the return type.

Related

C++ Returning Multiple Types as Reference

Ok so I'm trying to setup a template method that returns a reference of an undetermined type based on a parameter request. Everything looks fine but it keeps telling me that no overloaded method of the provided template method exists when I call it. The code looks something like this:
class IObj {
public:
int id;
}
class ObjOne : public IObj {}
class ObjTwo : public IObj {}
class ObjThree : public IObj {}
enum ObjectTypes {
O1Type,
O2Type,
O3Type
}
class ObjManager {
public:
std::vector< std::unique_ptr<ObjOne> > O1Holder;
std::vector< std::unique_ptr<ObjTwo> > O2Holder;
std::vector< std::unique_ptr<ObjThree> > O3Holder;
ObjManager() {}
template <class T>
T& GetObject(int oID, ObjectTypes oType) {
if(oType == ObjectTypes::O1Type) {
for(int i = 0; i < O1Holder.size(); i++) {
if(O1Holder[i]->id == oID) {
return *O1Holder[i];
}
}
}
else if(oType == ObjectTypes::O2Type) {
for(int i = 0; i < O2Holder.size(); i++) {
if(O2Holder[i]->id == oID) {
return *O2Holder[i];
}
}
}
else if(oType == ObjectTypes::O3Type) {
for(int i = 0; i < O3Holder.size(); i++) {
if(O3Holder[i]->id == oID) {
return *O3Holder[i];
}
}
}
}
}
int main() {
std::unique_ptr<ObjManager> oManager(new ObjManager());
ObjOne& a = oManager->GetObject(0, ObjectTypes::O1Type);
return 0;
}
Everything works fine, and I can make a method that returns a reference to the object stored in the vectors if I return their specific type, but I'm trying to reduce the redundancy of making many functions to return each different type. So I wanted to make a templated method that would return an object type based on which ever type I requested.
It's not giving me any errors it just keeps underlining the -> in the expression oManager->GetObject, and tells me there is no overloaded method for the template method call. Specifically it states "no instance of function template 'ObjManager::GetObject' matches the argument list, argument types are (int, ObjectTypes)" even though I'm passing an integer and ObjectTypes:: into the function's parameter list. I've looked all over for an answer to this but have not been able to find a similar situation to draw experience on.
EDIT: Sorry should have specified that this is a precursor to a vast list of vectors, I just put 3 of them for simplicity. That's why I'm trying to make a single function that can handle the return of different types so that I don't have to make a return function for every vector I create. And the purpose of returning a reference to the specified type is because each derived type will have unique data that is not in the base class, so I'm pulling the objects for editing.
As #tobi303 commented, you should definetly use the template Parameter T in your GetObject class. Then you would actually avoid repeating yourself as the Compiler will generate the code for you that you have repeated 3 times
template <class T>
T& GetObject(int oID) {
for(int i = 0; i < OHolder<T>.size(); i++) {
if(OHolder<T>[i]->id == oID) {
return *OHolder<T>[i];
}
}
While you would have to define a OHolder Template function, too.
It is not possible to change the return type of a function based on runtime information (such as your parameters), because they are obviously unknown to the compiler.
If you will always know at compile time which object type you are going to choose, you can use a trick:
Step 1: Turn your enum into a couple of empty structs:
struct O1Type {};
struct O2Type {};
struct O3Type {};
Step 2: Instead of using else ifs, use function overloading:
ObjOne& GetObject(int oID, O1Type) {/* TODO*/}
ObjTwo& GetObject(int oID, O2Type) {/* TODO*/}
ObjThree& GetObject(int oID, O3Type) {/* TODO*/}
You can now use
ObjOne& a = oManager->GetObject(0, O1Type());
(or, even better auto& a = oManager->GetObject(0, O1Type());)
You seem to be trying to use both run-time polymorphism AND the compile-time (template) polymorphism. It doesn't work this way. You cannot return multiple types from the SAME METHOD.
What you probably want to do is to either define a method like #yussuf described, or to fully start using run-time polymorphism - in which case you don't need three containers, and the type becomes part of the object ID.
I concur with #yussuf's approach. Just do that, it probably will solve your problem.
I would also recommend to use a hash / map instead of performing linear search, but this is a different story...
Root cause
Template argument type deduction can't be solely based on the return type of the function.
On the way to a solution
You could therefore add a dummy function argument to transfer the type information:
template <class T>
T& GetObject(int oID, ObjectTypes oType, T&x) {
...
}
and in main():
ObjOne& a = oManager->GetObject(0, ObjectTypes::O1Type, a);
Then the template type can be deduced.
But this will not solve your problem. This type deduction is at compile time, so that all the possible returns of the function should return the same type (or something that can be converted to it).
This is not the case of your code, which will lead to other compilation errors (see online failure).
The solution
The only workable solution is that you determine the common denominator to return. Make the function a non-template function returning an IObj&:
IObj& GetObject(int oID, ObjectTypes oType) {
...
}
You should then manage the return object as a polymorphic obhect as well. As the return is by reference, this is fine (i.e. no slicing occurs). The returned reference will really refer to the object returned, whatever its derived type could be. But you'd have to redesign your calling code for polymorphism:
IObj& a = oManager->GetObject(0, ObjectTypes::O1Type);
Online demo
But this is somewhat clumsy because you indicate in an enum the expected type, but then end with a reference to a parent that you can't handle so easily.
Conclusion
As you indicate in the function the expected return type, you'd better go for the solution in Yussuf's rexcellent answer, but applying the technique of the dummy argument for type deduction.
Ok so after much research, I have determined the best way to accomplish this is to create a custom container class like so:
#include <vector>
#include <memory>
class Base {
public:
int ID;
Base(int id) { ID = id; }
}
class A : public Base {
public:
int X;
A(int id) : Base(id) {}
}
class B : public Base {
public:
int Y;
B(int id) : Base(id) {}
}
template <class T>
class MyContainer {
private:
std::vector<std::unique_ptr<T>> internalContainer;
public:
MyContainer() {}
~MyContainer() {}
void CreateItem(int id) {
std::unique_ptr<T> newItem(new T(id));
internalContainer.push_back(std::move(newItem));
}
T& GetItem(int id) {
for(std::vector<std::unique_ptr<T>>::iterator it = internalContainer.begin(); it!= internalContainer.end(); ++it) {
if((*it)->ID == id) {
return **it;
}
}
}
}
int main() {
MyContainer<A> AList;
MyContainer<B> BList;
AList.CreateItem(0);
BList.CreateItem(0);
A& AOne = AList.GetItem(0);
B& BOne = BList.GetItem(0);
AOne.X = 10;
BOne.Y = 20;
std::cout << std::to_string(AOne.X) << "\n";
std::cout << std::to_string(BOne.Y) << "\n";
}
Let me know your opinions on if this is acceptable or if it can be improved! :)

Template substitution for function names

I'm using a third party C++ library which has a json parsing class that has
different functions like this:
GetInt
GetBool
GetString
GetDouble
I'd like to write a utility function that can access this class. I'm thinking of something like this:
class <template T>
class MyClass {
static T getValue(ThirdPartyClass someObj, const string &key) {
if(someObj[key].IsDouble())
return someObj[key].GetDouble();
else if (someObj[key].IsString())
return someObj[key].GetString();
// ... (for other types)
}
}
The caller of this class will hold the correct return type.
However this is ugly. Is there any way (using macro substitution for example) I can avoid the if conditions? The third party class has IsXXTypeXX and corresponding GetXXTypeXX functions (where XXTypeXX is Int, Double,String or Bool).
I know the return type when I call the function for eg:
int i = getValue(someObj, "intKey");
string s = getValue(someObj, "strKey");
So I dont need the if conditions at all. Ideally I would look to have something so
I would be able to do this:
int i = MyClass<int>::getValue(someObj, "intKey");
string s = MyClass<string>::getValue(someObj, "strKey");
Why not just write a bunch of static Get functions (GetInt/GetDouble...) that validates the input, returns the appropriate type result and throws an exception if it isn't that type?
Technically you can achieve the public interface that you've outlined there but that would involve very ugly looking template specialization.
It would probably be better if you just had a bunch of static functions instead. Here is what template specialization would look like:
template <typename T> class MyClass {
static T getValue(ThirdPartyClass someObj, const string &key) {
// handle types that you didn't specialize for
}
};
template <> class MyClass <string> {
static string getValue(ThirdPartyClass someObj, const string &key) {
return someObj[key].GetString();
}
};
template <> class MyClass <int> {
static int getValue(ThirdPartyClass someObj, const string &key) {
return someObj[key].GetInt();
}
};
//..
Skeleton key for software engineering: add an intermediate layer.
#include <string>
#include <cassert>
using std::string;
class Proxy {
public:
enum Type {
Int,
Bool,
String,
Double
};
Type type;
int i;
bool b;
string s;
double d;
operator int() const {
assert(type == Int);
return i;
}
operator bool() const {
assert(type == Bool);
return b;
}
operator string() const {
assert(type == String);
return s;
}
operator double() const {
assert(type == Double);
return d;
}
Proxy(int i) : type(Int), i(i) {}
Proxy(bool b) : type(Bool), b(b) {}
Proxy(string s) : type(String), s(s) {}
Proxy(double d) : type(Double), d(d) {}
}; // class Proxy
Proxy getValue(ThirdPartyClass someObj, const string &key) {
if (someObj[key].IsDouble())
return someObj[key].GetDouble();
else if (someObj[key].IsString())
return someObj[key].GetString();
//... (for other types)
}
int main() {
int i = getValue(someObj, "intKey"); // if type does not match, a exception will be thrown.
string s = getValue(someObj, "strKey");
}
The code you showed won't compile. You can't in the same function return a double, a string, and an int. What you'd have to do it specialize for each return type, and then call only the function for that type:
template <>
class MyClass<int> getValue(ThirdPartyClass someObj, const string& key) {
if(someOjb[key].IsInt()) return someObj[key].GetInt();
else { /* Maybe throw an exception */ }
};
and repeat for each type.
Now, you're probably thinking, "this is silly, how come I have to specialize each type?" That's because your JSON library is using type erasure, so you have to check the type at runtime. The only way to save yourself the work is if the library provides a templated get.
If you want, you could create a macro to stamp these instantiations out. It would take advantage of the # (stringification) and ## (concatenation) features of the preprocessor. It'll probably be clearer to just write them out.

Is it possible to have conditional declaration of methods and variables in templated classes?

I am trying to make a class that can have functions and members controlled by a template argument. I am thinking of something like this.
template<int control>
class ControlledDeclaration
{
public:
if(1 == control)
int Get() { return 0; }
else if(2 == control)
char* Get() { return "get"; }
else if (3 == control)
bool Get() { return true; }
};
void test_template()
{
ControlledDeclaration<1> c_int;
ControlledDeclaration<2> tx_int;
ControlledDeclaration<3> b_int;
}
If possible, how to do it?
The approach I would use is along the lines of specializing the details in a traits class and provide the interface using the template. In this trivial example there isn't much benefit of using traits rather than specializing the actual type but in general customizing the few points of variations is easier using traits than specializations.
template <int> struct ControlDeclarationTraits;
template <>
struct ControlDeclarationTraits<1> {
typedef int type;
static int value() { return 0; };
};
template <>
struct ControlDeclarationTraits<2> {
typedef char const* type;
static char const* value() { return "get"; }
};
template <>
struct ControlDeclarationTraits<3> {
typedef bool type;
static bool value() { return true; }
};
template<int control>
class ControlledDeclaration
{
public:
typename ControlDeclarationTraits<control>::type Get() {
return ControlDeclarationTraits<control>::value();
}
};
BTW, the type of string literals is char const[n] (for a suitable n) and not char[n], i.e., you can't really use a string literal to initialize a char*. It does work because it was deemed necessary to support existing code to assign string literals to char* but it is actually a lie: trying to assign a value to any of the values causes undefined behavior. Making the pointer const makes it obvious that the content isn't meant to be modified.
Have a look at boost::enable_if, that does exactly what you want.

Runtime value to type mapping

I've got a list of types which can be send over the network, take this example:
enum types {
E_T1,
E_T2,
E_T3,
E_T4
};
Now I have a list of classes which correspond to each of the types, let's say each is declared as class E_T1 {...}, class E_T2 {...}, etc.
They are not derived from a common base class and it's not possible to do so. Each of the classes has a verification method I need to invoke with the data send over the network. The client sends the data D and a id correspointing to the message type. I need to get hold of the object corresponding to the type. I can use C++0x features if needed.
What I've tried so far is using specialized templates for the types, holding a typedef for the object related to it. This was obviously a stupid idea as templates parameters need to be compile time constant so doing something along getType<data.id()>::type is not possible.
Then I tried using Boost.Variant to get a common returnable type like this (used mpl vector to iterate over the registered types at runntime for debbuging):
template <typename C>
struct getType() {
typedef C type;
}
typedef boost::mpl::vector<
getType<E_T1>,
getType<E_T2>,
getType<E_TX>...
> _types;
typedef boost::make_variant_over<_types>::type _type;
//use a map to store each type <-> id
boost::unorderd_map<types, _type> m;
m[E_T1] = getType<E_T1>();
m[data.id()]::type x; //<- access type, can now call x.validate(data)
The problem with this is that it's limited to 20 entries per variant per default. This can be overwritten but from what I understood the overhead per type should be considered and we are talking about a few thousand types here.
Also tried boost.any but it doesn't hold any type information so that's out of the question again. Has anyone any good ideas how this can be solved elegantly?
Looking for something where I don't have to write a 1k switch statement anytime I handle a type.
All types are nown at compile type, same goes for their corresponding IDs.
Id -> Type resolving needs to happen at runtime though.
Thanks in advance,
Robin.
External Polymorphism (*)
It's a widely known idiom, however it's widely used: I first encountered it in the shared_ptr implementation and it's been quite useful in my toolbox.
The idea is to actually create a base class for all those types. But not having them derive from it directly.
class Holder {
public:
virtual ~Holder() {}
virtual void verify(unsigned char const* bytes, size_t size) const = 0;
}; // class Holder
template <typename T>
class HolderT: public Holder {
public:
HolderT(): _t() {}
virtual void verify(unsigned char const* bytes, size_t size) const {
_t.verify();
}
private:
T _t;
}; // class HolderT
template <typename T>
std::unique_ptr<Holder> make_holder() {
return std::unique_ptr<Holder>(new HolderT<T>());
}
So, it's the classic strategy of adding a new level of indirection.
Now, you obviously do need a switch to move from value to class. Or perhaps... a map ?
using maker = std::unique_ptr<Holder> (&)();
using maker_map = std::unordered_map<types, maker>;
std::unique_ptr<Holder> select(types const E) {
static maker_map mm;
if (mm.empty()) {
mm.insert(std::make_pair(E_T1, make_holder<EC_T1>));
// ...
}
maker_map::const_iterator it = mm.find(E);
if (it == mm.end()) { return std::unique_ptr<Holder>(); }
return (*it->second)();
}
And now you can handle them polymorphically:
void verify(types const E, unsigned char const* bytes, size_t size) {
std::unique_ptr<Holder> holder = select(E);
if (not holder) { std::cerr << "Unknown type " << (int)E << "\n"; return; }
holder->verify(bytes, size);
}
Of course, you're welcome to make the strategy vary according to your needs. For example moving the map out of select so that you can register your types dynamically (like for plugins).
(*) At least that's the name I have for it, I would quite happy to find out it's already been named.
I'll assume you have a generic way of handling a message, such as for example an overloaded function:
void handle_message(const E_T1& msg);
void handle_message(const E_T2& msg);
//...
Now, you do not really need to get the object's type. All you need is a way to handle a message of that type, given the undecoded message.
So, I recommend you populate a map of factory functions:
std::unordered_map<types, std::function<void (unsigned char const* bytes, size_t size)> handlers;
handlers[E_E1] = [](unsigned char const* bytes, size_t size) { handle_message(E_T1(bytes, size)); };
// ...
Then, once you've decoded the type, you can use handlers[type](bytes, size) to decode and handle a message.
Try variadic templates and your already defined getType class:
enum types { T1_ID, T2_ID, .... };
class T1; class T2; class T3; ....
template <types t> struct getType;
template <> struct getType<T1_ID> { typedef T1 type; };
template <> struct getType<T2_ID> { typedef T2 type; };
...
And the operation verify:
template <types...>
struct type_operation;
template <types t1, types... rest>
struct type_operation<t1, rest...>
{
void verify(types t)
{
if (t == t1)
{
typename getType<t1>::type a;
a.verify(); // read from network and verify the rest of data....
}
else type_operation<rest...>::verify(t, data);
}
};
template <>
struct type_operation<>
{
void verify(types t)
{
ostringstream log; log << "not suppoted: " << t;
throw std::runtime_error(log.str()); //
}
};
Usage:
typedef type_operation<T1_ID, T2_ID, T3_ID, ,,.., TN_ID> type_mapping;
types id;
readFromNetwork(id);
type_mapping::verify(id);

How to make this specialized function work

Here's the deal. I've looked on this forum and I didn't find the information I'm searching for or I'm probably not able to repeat it for my problem. I have a class Table which is generic and I have a class named MyString.
template <typename typeGen, int DIM>
class Table {
public:
TableauGenerique() : index_(0) { //On initialise courant à 0
}
void add(typeGen type);
private:
typeGen tableGen_[DIM];
int index_;
};
My problem is with the add function.
I sometimes have to do this in the main.cpp: (which works well)
Table <float,6> tabFloat;
tabFloat.add(1.6564);
and at one point, I need to do this which doesn't work because I need to specialize the add function to create an object of MyString, to pass it the string and then store the object in the array (tableGen) :
TableauGenerique <MyString,4> tabString;
So I tried this (after the class), without success.
template <typename typeGen, int DIM>
void Table<typeGen,DIM>::add(typeGen type){ //Which is the generic one for float or ints
if(index_ < DIM) {
tableGen_[courant_] = type;
index_++;
}
}
template <class typeGen, int DIM>
void Table<typeGen,DIM>::add<string>(typeGen type) { //(line 75) Which is the specific or specialized function for myString
MyString str(type);
if(index_ < DIM) {
tableGen_[courant_] = str;
index_++;
}
}
So, How can I make this work because it doesn't compile at all, saying: line75 : error: expected initializer before '<' token and in the main it says not matching function to call Table::add(const char[6]),
I hope everything is clear enough. Let me know if somethings is unclear.
Thank you very much for your help !
template <class typeGen, int DIM>
void Table<typeGen,DIM>::add<string>(typeGen type)
You're trying to specialize add() when in fact it is not a function template to begin with. How do you expect it to work?
You probably meant: (specialization of the class)
template <int DIM>
void Table<string,DIM>::add(string type)
But then this is allowed only if you specialize the class itself. Without specializing the class, the above code would give compilation error!
EDIT:
You can read these online tutorials:
Introduction to C++ Templates
14.5 — Class template specialization
Template Specialization and Partial Template Specialization
Explicit specialization (C++ only)
If you can control the code of the MyString class, you can provide constructors that act as implicit conversions from float to MyString. An example:
#include <string>
#include <sstream>
#include <iostream>
class MyString {
public:
MyString(float number) {
std::stringstream buffer;
buffer << number;
value = buffer.str();
}
void print() {
std::cout << value << std::endl;
}
private:
std::string value;
};
template <class T>
class Foo {
public:
void DoStuff(T item) {
item.print();
}
};
int main() {
Foo<MyString> foo;
foo.DoStuff(1.342); // implicitly converts float to MyString
return 0;
}
This way, you do not need any specialization of the add method. However, implicit conversions are tricky, and you have be careful not to invoke them accidentally, and they may create ambiguities.
EDIT: Upon a second thought, my suggestion below is basically equivalent to
Table<MyString,4> tabString;
tabString.add(MyString("whatever"));
and therefore excessive and/or does not solve the problem. Feel free to ignore :)
I would extend the class Table with a generic method to add something from which you can construct an object of the desired type:
template <typename typeGen, int DIM>
class Table {
public:
Table() : index_(0) {}
void add(typeGen type);
// The additional method
template<typename T> void add(const T& src);
private:
typeGen tableGen_[DIM];
int index_;
};
template<typename typeGen, int DIM>
template<typename T>
void Table<typeGen,DIM>::add(const T& src) {
if(index_ < DIM) {
tableGen_[courant_] = typeGen(src);
index_++;
}
}
Note construction of a temporary typeGen object before the assignment.
Assuming that MyString object can be constructed from a string literal, i.e. from const char*, you can then use it as following:
Table<MyString,4> tabString;
tabString.add("whatever");
or if the above assumption is wrong, the following should probably work (because you constructed a MyString instance from a string instance):
tabString.add(string("whatever"));