Template function overload not called as expected - c++

My situation is the following:
I have a template wrapper that handles the situation of values and object being nullable without having to manually handle pointer or even new. This basically boils down to this:
struct null_t
{
// just a dummy
};
static const null_t null;
template<class T> class nullable
{
public:
nullable()
: _t(new T())
{}
nullable(const nullable<T>& source)
: _t(source == null ? 0 : new T(*source._t))
{}
nullable(const null_t& null)
: _t(0)
{}
nullable(const T& t)
: _t(new T(t))
{}
~nullable()
{
delete _t;
}
/* comparison and assignment operators */
const T& operator*() const
{
assert(_t != 0);
return *_t;
}
operator T&()
{
assert(_t != 0);
return *_t;
}
operator const T&() const
{
assert(_t != 0);
return *_t;
}
private:
T* _t;
};
Now with the comparison operators I can check against the null_t dummy in order to see whether it is set to null before actually trying to retrieve the value or pass it into a function that requires that value and would do the automatic conversion.
This class has served me well for quite some time, until I stumbled about an issue. I have a data class containing some structs which will all be outputted to a file (in this case XML).
So I have functions like these
xml_iterator Add(xml_iterator parent, const char* name,
const MyDataStruct1& value);
xml_iterator Add(xml_iterator parent, const char* name,
const MyDataStruct2& value);
which each fill an XML-DOM with the proper data. This also works correctly.
Now, however, some of these structs are optional, which in code would be declared as a
nullable<MyDataStruct3> SomeOptionalData;
And to handle this case, I made a template overload:
template<class T>
xml_iterator Add(xml_iterator parent, const char* name,
const nullable<T>& value)
{
if (value != null) return Add(parent, name, *value);
else return parent;
}
In my unit tests the compiler, as expected, always preferred to choose this template function whereever a value or structure is wrapped in a nullable<T>.
If however I use the aforementioned data class (which is exported in its own DLL), for some reason the very first time that last template function should be called, instead an automatic conversion from nullable<T> to the respective type T is done, completely bypassing the function meant to handle this case. As I've said above - all unit tests went 100% fine, both the tests and the executable calling the code are being built by MSVC 2005 in debug mode - the issue can definitely not be attributed to compiler differences.
Update: To clarify - the overloaded Add functions are not exported and only used internally within the DLL. In other words, the external program which encounters this issue does not even include the head with the template overloaded function.

The compiler will select primarily an exact match before it finds a templated version but will pick a templated "exact match" over another function that fits, eg, one that uses a base class of your type.
Implicit conversions are dangerous and often bite you. It could simply be that way you are including your headers or the namespaces you are using.
I would do the following:
Make your constructors of Nullable all explicit. You do this with any constructors that take exactly one parameter, or can be called with one (even if there are more that have default values).
template<class T> class nullable
{
public:
nullable()
: _t(new T())
{}
explicit nullable(const nullable<T>& source)
: _t(source == null ? 0 : new T(*source._t))
{}
explicit nullable(const null_t& null)
: _t(0)
{}
explicit nullable(const T& t)
: _t(new T(t))
{}
// rest
};
Replace the operator T& conversions with named functions. Use ref() for the non-const and cref() for the const.
I would also complete the class with
assignment operator (needed for rule of 3)
operator-> two overloads as you are propagating the constness.
If you plan to use this for C++0x also the r-value copy and assign, which is useful in this case.
By the way, you do know your deep copy won't work with base classes as they will slice.

Well, since no real answer was found so far, I've made a workaround. Basically, I put the aforementioned Add functions in a seperate detail namespace, and added two template wrapper functions:
template<class T>
xml_iterator Add(xml_iterator parent, const char* name,
const T& value)
{
return detail::Add(parent, name, value);
}
template<class T>
xml_iterator Add(xml_iterator parent, const char* name,
const nullable<T>& value)
{
return value != null ? detail::Add(parent, name, *value) : parent;
}
I found this to always properly resolve to the correct one of those two functions, and the function for the actual contained type will be chosen in a seperate step inside these, as you can see.

Related

Overloading specialized assignment operator based on typename

Okay, the title is a mouthful and hopefully specific enough, but I'm running into a C++ issue which I think is possible, I just can't seem to find the proper syntax.
I have a simple template-based property class:
template <typename T>
class Property
{
public:
Property<T> &operator = (const T &src)
{
m_data = src;
return *this;
};
operator const T& () const
{
return m_data;
}
private:
T m_data;
};
I need to assign values from a QVariant, which is also sort of a property but without templates. At the moment I am deferencering the values explicitly when assigning:
Property<QString> p1;
Property<int> p2;
p1 = var1.toString();
p2 = var2.toInt();
This works but it is tedious and I'm sure the compiler can do the work for me. So, I tried implementing specialized assignment operators based on the typename of the Property; in other words, if the template specialization is based on a QString use one function, if it is based on an int use another function, et cetera.
I tried things like:
Property<QString> &operator = (const QVariant &ref)
{
m_data = ref.toString ();
return *this;
};
or...
template <typename int> &Property<int>::operator = (const QVariant &ref)
{
m_data = ref.toInt ();
return *this;
};
or...
template<> Property<T> &Property<QString>::operator = (const QVariant &ref)
{
m_data = ref.toString ();
return *this;
}
..both inside and outside of the class declaration but to no avail. I get errors like "expected nested-name-specifiers", "two or more data types in declaration of parameters" and the like.
Any pointers to the correct syntax would be appreciated!
PS: the first declaration compiles witout error, but adding the same declaration for <int> makes it ambiguous since only the return type differs.
Compiler is GCC 4.8.2 with --stdc=c++11 enabled.
Although the answer of paddy seems correct, it seems to me tedious to generalize it (implement a specialzed assignment operator to all the types that a QVariant can hold, in addition to QString and int).
An easier solution would be to specialize the assignment operator once for all, in a way that benefits from the built-in conversions that the QVariant provides:
Property& operator= (const QVariant& src)
{
assert(src.canConvert<T>());
m_data = src.value<T>();
return *this;
}
The original class definition is a bit wrong, as pointed out by Kirill Kobelev in your question's comments section. Now, let's fix that and also add another operator=:
template <typename T>
class Property
{
public:
Property & operator=( const T & src )
{
m_data = src;
return *this;
}
// This one must be specialized
Property & operator=( const QVariant & src );
const T & operator() const
{
return m_data;
}
private:
T m_data;
};
The specialization is therefore quite simple. Here's ones for QString and int:
template <>
Property<QString> &
Property<QString>::operator=( const QVariant & src )
{
return operator=( src.toString() );
}
template <>
Property<int> &
Property<int>::operator=( const QVariant & src )
{
return operator=( src.toInt() );
}
Now you are free to assign QVariant values directly to any Property which provides that specialization. If you try to do it on a class that did not specialize then you will get an error.
I don't have the reputation to comment, nor the expertise to claim insight so please don't take this as an "answer".
But your question reminded me of a lesson on Cpp, Overloads and Functions over at http://www.cplusplus.com/doc/tutorial/functions2/ .
Excerpt:
"In the example above, we used the function template sum twice. The first time with arguments of type int, and the second one with arguments of type double. The compiler has instantiated and then called each time the appropriate version of the function.
Therefore, result will be a variable of the same type as the parameters a and b, and as the type returned by the function.
In this specific case where the generic type T is used as a parameter for sum, the compiler is even able to deduce the data type automatically without having to explicitly specify it within angle brackets."
Apologies if I missed the point, but thought this may help.

Can I define implicit conversion from std::function to std::shared_ptr<MyClass>?

I have a class that works as a predicate to select value from list.
class Predicate {
public:
// In this example, I am using QString as value type
// this is not what happens in actual code, where more complex data is being validated
virtual bool evaluate(const QString& val) const = 0;
};
Originally, I used lambda functions but this created lot of repetitive garbage code. So instead, I want to use predicate classes that use inheritance. For example:
class PredicateMaxLength: public RowPredicate {
public:
PredicateMaxLength(const int max) : maxLength(max) {}
virtual bool evaluate(const QString& val) const {return val.length()<maxLength;}
protected:
const int maxLength;
};
To allow inheritance do it's deed, pointers are given rather than values:
class SomeDataObject {
// Removes all values that satisfy the given predicate
int removeValues(const std::shared_ptr<Predicate> pred);
}
Now we are surely stil going to use lambdas in cases where code would not be repetitive (eg. some special case). For this purpose, PredicateLambda has been created:
typedef std::function<bool(const QString& val)> StdPredicateLambda;
class PredicateLambda: public Predicate {
public:
PredicateLambda(const StdPredicateLambda& lambda) : RowPredicate(), callback_(lambda) {}
virtual bool evaluate(const QString& val) const override {return callback_(val);}
protected:
const StdPredicateLambda callback_;
};
The nasty effect of this is that whenever lambda is used, it must be wrapped into PredicateLambda constructor:
myObject.deleteItems(std::make_shared<PredicateLambda>([]->bool{ ... lambda code ... }));
This is ugly. I have two options:
for every function that accepts predicate, have an overload that does the conversion seen above. This duplicates number of methods in header file
Have an implicit conversion from std::function<bool(const QString& val)> to std::shared_ptr<Predicate> which would execute this:
std::shared_ptr<Predicate> magicImplicitConversion(const StdPredicateLambda& lambdaFn) {
return std::make_shared<PredicateLambda>(lambdaFn);
}
I came here to ask whether the second option is possible. If it is, does it carry any risk?
If you don't want to use template to not expose code, you may use std::function:
class SomeDataObject {
// Removes all values that satisfy the given predicate
int removeValues(std::function<bool(const QString&)> pred);
};
and your predicate
class PredicateMaxLength {
public:
explicit PredicateMaxLength(int max) : maxLength(max) {}
bool operator ()(const QString& val) const {return val.length()<maxLength;}
protected:
int maxLength;
};
So you can use either
SomeDataObject someDataObject;
someDataObject.removeValues(PredicateMaxLength(42));
someDataObject.removeValues([](const QString& s) { return s.size() < 42; });
You want polymorphism, and you don't want to use template-style header lambdas. And you want to be able to have a few default cases.
The right answer is to throw out your Predicate class.
Use using Predicate = std::function<bool(const QString&)>;.
Next, note that your Predicate sub-types are basically factories (the constructor is a factory) for Predicates with some extra state.
For a std::function, such a factory is just a function returning a Predicate.
using Predicate = std::function<bool(const QString&)>;
Predicate PredicateMaxLength(int max) {
return [max](QString const& str){ return val.length()<max; }
}
where the body of PredicateMaxLength goes in a cpp file.
If you have an insanely complicated set of state for your Predicate-derived class, simply give it an operator() and store it within a std::function. (In the extremely rare case that you have some state you should store in a shared ptr, just store it in a shared ptr).
A std::function<Signature> is a regular type that is polymorphic. It uses a technique known as type erasure to be both a value and polymorphic, but really you can call it magic.
It is the right type to use when you are passing around an object whose only job is to be invoked with some set of arguments and return some value.
To directly answer your question, no, you cannot define a conversion operator between a std::function and a std::shared_ptr<yourtype> without making your program ill formed, no diagnostic required.
Even if you could, a std::function is not a lambda, and a lambda is not a std::function. So your conversion operator wouldn't work.

Return NULL from a C++ template

I have to create a template function that searches an element in a map variable. If the element exists, the function must return it. Otherwise it must return NULL.
template <class K, class E> E dictionary<K,E>::research(K key) {
// map<K,E> elements;
if(elements.find(key) != elements.end()) {
return elements.find(key)->second;
} else {
return NULL;
}
Since the return type is E, returning NULL gives me always an error. How can I make this work? Or I have to structure my function differently?
This is a school homework assignment and I must return NULL, no alternatives. I'd personally do differently if I could.
The design of this function is incorrect. It is perfectly possible that NULL is simply incompatible with the type E. For instance, suppose that E is a struct, or a std::string and so on.
This is a school homework assignment and I must return NULL, no alternatives.
Either your homework assignment is incorrect, or you have misunderstood its requirements. It is possible that you are expected to return a pointer to E?
Instead of returning pointers, you could consider returning something like boost::optional, i.e. a type that is either set to contain a valid object or in an invalid state. That mimics a pointer in some way, but is more explicit
The following is just to show the principle, the implementation can for sure be optimized.
template<typename T> class Optional {
public:
Optional(E e):
isValid(true),
mValue(e)
{}
Optional(): isValid(false), mValue() {}
bool isDefined() const {return isValid;}
E getOrElse(E const& other) const {return (isValid) ? (mValue) : (other);}
E get(E const {return mValue;}
private:
bool isValid;
T mValue;
};

Less writing for type conversion possible?

Let's assume you loaded a dynamic library using dlopen() or LoadLibrary() on Windows, and you want to get a symbol from it and cast it to a specific function type. It is so unbelievable redundant to write the type twice!
void (*Test)(int, float) =
reinterpret_cast<void (*Test)(int, float)>(dlsym(handle, "Test"));
I want the code to be compilable without the C++11 standard, therefore the auto keyword is not an option. I tried using templates because compilers can often detect the template parameters from the given parameters, but it does not seem to work for the type of the assignment value.
template <typename T>
T GetSym(void* handle, const char* symbol) {
return (T) dlsym(handle, symbol);
}
void (*Test)(int, float) = GetSym(handle); // does not compile
Is there a way to bring less redundancy into the code? When retrieving a huge number of functions from a dynamically loaded library, it is awful to write each and every cast twice!
You can do this with an evil templated conversion operator.
struct proxy {
public:
proxy(void* ptr) : ptr(ptr) {}
template <typename T>
operator T() const {
return reinterpret_cast<T>(ptr);
}
private:
void* ptr;
};
proxy GetSym(void* handle, const char* symbol) {
return proxy(dlsym(handle, symbol));
}

Build error: base specifier must name a class

I am trying to build a big project in Mac OS X with cmake and ran into following error which i am unable to solve.
Archive.hpp:92:30: error: base specifier must name a class
struct Derived : T, Fallback { };
Code:
template<typename T>
class has_save_func
{
struct Fallback { int save; }; // add member name "X"
struct Derived : T, Fallback { };
...
Furthermore i have following:
Archive.hpp:137:13: error: type 'unsigned long' cannot be used prior to '::'
Code:
template <class A>
static bool save(const A& data, class OutputArchive& oarchive, const std::string& id, typename boost::enable_if_c<has_save_func<A>::value, A>::type* def=NULL){
// todo check if A actually is friend with Access class, else return false
A::save(data, oarchive); // ! Error on this line !
return true;
}
template <class A>
static bool save(const A& data, class OutputArchive& oarchive, const std::string& id, typename boost::disable_if_c<has_save_func<A>::value, A>::type* def=NULL){
// todo check if A actually is friend with Access class, else return false
return serialization::save<A>( data, oarchive, id);
}
Code calling (OutputArchive.hpp):
template<class T>
void write(const T& data, const std::string& id){
// the data method must have an implementation of load/save and if not then we try the generic write
// method which could provide a solution by the implementation itself
writeEnterScope(id);
try {
Archive::Access::save<T>(data, *this, id);
} catch (...){
// we fall back to this call
boost::any adata(data);
write(adata, id);
}
writeLeaveScope(id);
}
Code serializeutil.cpp
void save(const rw::math::Q& tmp, OutputArchive& oar, const std::string& id){
oar.write(tmp.size(), "size");
for(int i=0;i<tmp.size();i++){
oar.write(tmp[i],"q");
}
}
Could it be a problem with the compiler im using?
Both errors point to the same: you are trying to use your templates with a non-class, most probably unsigned int. In the first case, you would be trying to have Derived inherit from unsigned int, which is illegal; in the second, you would be trying to call a static method (save()) on unsigned int, which is illegal again. Looking at the code calling the templates would clarify the issue.
UPDATE: From the information added to the question we can now conclude that this was indeed the case. tmp.size(), is most probably an unsigned int, so you are calling oar.write() with an unsigned int; this, in turn, calls save() with an unsigned int, so it tries to call unsigned int::save(), which is illegal, and instantiate class has_save_func<unsigned int>, which tries to define struct Derived : unsigned int, Fallback which is illegal again.
I'm afraid you will need to redesign your classes if you want them to work with built-in types, such as unsigned int. You might do a complete redesign or just overload functions write() or save(), depending on what you have available.
I think that i may be responsible for the mentioned pieces of code. Something is missing though, and multiple persons already noticed this. The overloaded write functions on the OutputArchive which currently looks something like this:
virtual void writeEnterScope(const std::string& id) = 0;
virtual void writeLeaveScope(const std::string& id) = 0;
virtual void writeEnterArray(const std::string& id) = 0;
virtual void writeLeaveArray(const std::string& id) = 0;
// writing primitives to archive
virtual void write(bool val, const std::string& id) = 0;
virtual void write(int val, const std::string& id) = 0;
virtual void write(unsigned int val, const std::string& id){ write((int)val,id); }
virtual void write(boost::uint64_t val, const std::string& id) = 0;
virtual void write(double val, const std::string& id) = 0;
virtual void write(const std::string& val, const std::string& id) = 0;
The serialization part of the software was not supposed to be used yet, but it ended up in the build system anyways. If you comment out the serialize directory in CMakeLists.txt in src/rwlibs then it should work. Or add a write function for an unsigned long:
virtual void write(unsigned long val, const std::string& id){};
And yes, i did look into Boost.Serialization before venturing into creating yet another serialization framework. I was however trying to create something that would be less intrusive, less templated and more user friendly.... Guess i failed at that...
First, it would be better to use existing solution like Boost.Serialization. It's already debugged and works in all the cases you may need.
However, you should still know where your current code has problems and how to do template machinery like this. So:
oar.write(tmp.size(), "size");
^^^^^^^^^^
This is unsigned int. And you do need to serialize it. So you need a write, that can accept primitive types. There are two options:
Write non-template overloads for primitive types. Non-template overloads have priority over template ones, so if you write explicit non-template overload with unsigned int first argument, the template won't be instantiated and there won't be any error. You will however need overloads for each possible primitive type separately, because template that matches exactly will be still preferred over non-template overload that requires conversion.
Use free save function instead of method. Advantage of method is that it can be virtual, but you don't usually need that with template. Advantages of free function are that they can be defined for non-class types and that they can be defined for already existing classes, both of which you often do need in templates. So you would change all instances of the save method to free function, drop the has_save_func altogether and overload the save function for primitive types you need.
Amend the has_save_func with check whether the template argument is a class type. Non-class types don't have methods, so that's what the other variant will do. You can either use the boost::is_class or implement something similar. Boost actually implements it by enumerating all the other options, but it can also be implemented using pointer-to-member, which will cause SFINAE when given non-class type. Unfortunately you don't have anything to cause SFINAE when given class type, so you have to combine with function templates and sizeof and end up with really tricky stuff (I'm sure I've seen it, but really don't remember it).