1

I have a template function that can return different types.

template <class typ>
typ GetRespVal_byField(const std::string & _fname){
for (pqxx::result::const_iterator row = m_result.begin();
     row != m_result.end();
     ++row)
    {
        if (!row[_fname].is_null())
            return row[_fname].as<typ>();
        else
            return NULL; //this is what i want 

    }
}

Is it a correct implementation?

Krcn U
  • 411
  • 1
  • 9
  • 16
  • it gets compiled but i am not sure if it is a correct way to do it .. – Krcn U Jan 08 '16 at 13:16
  • The only one who can determine if it is a "correct way to do it" is you. Because only you could possibly know what is the correct behavior for your own code. – Sam Varshavchik Jan 08 '16 at 13:24
  • In c++0x and forward you may want to consider the `nullptr` http://stackoverflow.com/questions/20509734/null-vs-nullptr-why-was-it-replaced. – patrik Jan 08 '16 at 13:54

5 Answers5

3

As far as typ can take NULL value (or if a typobject can be constructed from a NULLvalue), yes, you can. If type is a pointer or an int for instance.

You can even return foo_bar....if foo_bar is a valid typvalue, it will work....

Template resolution is done upon compilation, so, as YSC commented, if it compiles, then yes, it's allowed in term of type checking (now, the fact that code compile does not necessarily mean it will work at runtime, but, for your specific question, it's good enough)....

jpo38
  • 20,821
  • 10
  • 70
  • 151
2

is it possible to create template function returning null?

Generally, yes, of course. Why shouldn't a template function be able to do that?

However...

Is it a correct implementation?

This depends on your definition of "correct" :)

For example, if you try to instantiate the function with std::string for typ, then returning NULL invokes undefined behaviour (because you would try to construct a std::string from a null pointer). Undefined behaviour is usually considered a very incorrect thing.

Consider Boost.Optional as an alternative to represent the non-existence of something. It's more generic than NULL.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
2

It's possible, but might not always be a good idea. For example, if typ is a string, then your code would compile, because NULL would be interpreted as char * from which to implicitly construct a string. However, the code would fail at runtime when the else branch is hit, because trying to construct a string from NULL is undefined behavior that would almost certainly lead to an access violation.

So I would suggest at least two improvements to your code.

  1. Use type traits in combination with a static_assert to assure that typ is a pointer type. Add this to your template function:

    static_assert(is_pointer<typ>::value, "<typ> must be a pointer type");
    

    This rules out types that are not pointers, but are constructible from a pointer, and additionally makes the error message more clear to the user.

  2. Return nullptr rather than NULL - mostly to make the intention more explicit, but also to avoid hypothetical scenarios when a conversion to integral type would be a bad thing (unlike NULL, nullptr is not implicitly converted to integral types).

kfx
  • 8,136
  • 3
  • 28
  • 52
1

More generally, compiling a template doesn't do much. Microsoft only recently abandoned something one could roughly call a text replacement implementation for templates:

The method chosen to implement this [templates, in the old compiler] was to do some minimal parsing of a template and then capture the whole template as a string of tokens (this is very similar to how macros are handled in the compiler). Later, when a template is instantiated, that token stream would be replayed through the parser and template arguments would be replaced.

The reason this was abandoned is that it is not quite sufficient to implement templates correctly. But a template in C++ is still very much a template in the semantic sense, which is why the the usual method to compile template using code involves having the template source available.

This is a striking contrast to C# which compiles standalone templates in the strict sense (to IL, of course).

Instantiating a template does more:

#include<iostream>

using namespace std;

// this works;
template<typename T> T f(T t)
{
    return cout;
}       

// this doesn't 
// double  d = f(1.0);
Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
0

You could write a type trait class which would define a NULL for any type you use. I suppose you would have problem with that - what NULL would you specify for std::string? You could change your function signature and return std::pair<typ, bool> where:

  1. if non NULL value is returned, then first is equal to returned value and second to true.
  2. if NULL value should be returned, then first is equal to default initialized typ, and second is false
marcinj
  • 48,511
  • 9
  • 79
  • 100