I'm having difficulty getting the correct syntax for a template specialisation which accepts a regular c-style string. For example
namespace RubyUtils
{
template<class T> VALUE toValue(const T& v);
};
template<> VALUE toValue(char const* & v)
{
return toValue<string>(v);
}
and then at the call site
return RubyUtils::toValue("Life the universe and everything");
gives an error
unresolved external symbol "unsigned long __cdecl RubyUtils::toValue<char const [33]>(char const (&)[33])"
how should I structure the specialisation to enable passing in c-style strings?
UPDATE: Fixed the template specialisation to have correct syntax template => template<>
I think that the problem you're encountering is probably related to the fact that you've defined two templates - one inside of the namespace, and one out. The error is likely due to this confusion.
But more importantly, as a general rule, you do not want to specialize function templates. Template specialization for function has lots of funky rules associated with it that almost universally result in the wrong thing getting called. Rather, just use regular function overloading:
namespace RubyUtils
{
template<class T> VALUE toValue(const T& v);
VALUE toValue(char const* v)
{
return toValue<string>(v);
}
};
The way function overloading works, calling the toValue function with a C-style string will cause the non-template toValue to get selected ahead of the toValue template, essentially doing the specialization for you. More generally, with function templates, prefer using overloading to specialization. It's just safer.
Related
The following code looks legitimate but doesn't compile
void f() {}
template<bool>
struct call_any
{
template<typename F>
static void call(F f) {}
};
template<bool B>
void call_f()
{
call_any<true>::call<void (&)()>(f); // OK
call_any<false>::call<void (&)()>(f); // OK
call_any<B>::call<void()>(f); // OK
call_any<B>::call<void (&)()>(f); // expected primary-expression before '>'
}
Why there is an error and what does it mean?
When you are dealing with types that are dependent on the template parameters within a template, the compiler doesn't know what kinds of things the members of that type are. Unless you specify otherwise, it assumes that the members are not types and not templates. Because of this, it is trying to treat < as a less-than operator, but it becomes impossible to parse the expression that way by the time it reaches the >.
To get rid of the error you should use this instead:
call_any<B>::template call<void (&)()>(f);
This tells the compiler explicitly that call is a template, so it should treat the < as the beginning of the template parameters and not a regular less-than operator.
This should use template as well:
call_any<B>::call<void()>(f);
The only reason you don't see the error on this line is that there is a way to parse it as a non-template:
(call_any<B>::call < void() ) > (f);
Although odd, it is syntatically valid, so the compiler gets past that line, and the first error you see is the one you mention. However, without the template keyword, you would eventually get an error once call_f was actually instantiated (probably -- there are weird ways it could work).
The first two examples are okay without using the template keyword. Since the type isn't dependent on the template parameters, it can be determined that call is a template while call_f is being parsed.
You might ask: "Why can't the compiler figure out it is a template? I've defined it as a template in the code right above!". The issue is specialization. You could specialize the template and do something completely different than what the primary template specifies:
template<>
struct call_any<false>
{
static const int call = 5;
};
This specialization could occur even after call_f is defined, so the compiler can't rely on what the primary template for call_any says when it is parsing call_f.
I know there are other questions like this but they are not very clear.
Now I feel as though this is a stupid question because I'm sure I already have the answer but let me ask anyways.
So I basically have a function that takes in a string and then based on the appropriate variable type it converts it like so:
template<class T>
void ConvertValue(std::string str, T &variable)
{
variable = static_cast<T>(str);
}
so this seems to be fine correct? But the thing is that you cannot convert a string to say an int or a float so therefore I would have to do template specialization for ints and floats and for other types it can't convert to so what I'm asking is should I have something like this:
void ConvertValue(std::string str, int &variable) { variable = atoi(str.c_str()); }
void ConvertValue(std::string str, float &variable) { ... }
void ConvertValue(std::string str, double &variable) { ... }
void ConvertValue(std::string str, std::vector<int> &variable) { ... }
..etc
or should I use template specialization? Which one would make more sense? I'm leaning towards function overloading because majority of the types are going to have their own conversion function so since they slightly differ function overloading makes logical sense to me but I don't know if I'm missing something.
Should I stick with function overloading? Or switch to template specialization?
If the internals of the function are going to have to be different for each type and potentially include type checks, it is simpler and cleaner to just have multiple functions.
If on the other hand you had a bunch of classes with a toString() method for conversion. Then you would use a template because the internals would always be the same.
I would use std::istringstream:
template <typename T>
T ConvertValue(const std::string& str)
{
std::istringstream iss(str);
T ret;
if (!(iss >> ret))
{
throw std::bad_cast("Failed!");
}
return ret;
}
This should be the answer to your questions :
how to get typeof variable in C++
and yes it should be template specialization.
Short answer :
You are right. Function Overloading makes more sense. Function base template specialization does not overload.
Long Answer
function base template specializations are class 2 citizen, functions are first class citizen.
If you write an overloaded function nobody can write anything overloading or hiding your code without getting a compiler error. If you write a function base template specialization anybody can overload it with a function overload matching that function base template specialization signature. (yes, the programmer writing the specialization will be pissed of at your function, but will have to live with that).
If you want a better question for a better answer, read Why Not Specialize Function Templates? : http://www.gotw.ca/publications/mill17.htm
I wonder why template specializations make sense?
Aren't the following things equivalent?
Template specialization:
template <typename T>
void f(T t) {
something(t);
}
template <>
void f<int>(int t) {
somethingelse(t);
}
Non-template function instead of specialization:
void f(int t) {
somethingelse(t);
}
I believe these are the same because the non-template function will always be preferred.
This is the answer I came up with:
It's different if the template parameter is not a parameter of the function being defined:
template <typename T>
void f() {
T t;
something(t);
}
template <>
void f<int>() {
int t;
somethingelse(t);
}
In this case defining:
void f() {
int t;
somethingelse(t);
}
would make all the template versions unuseable.
Maybe somebody else has better ideas. :)
The question boils down to determining when the specialization will be used that the overload cannot. There are different situations where this is the case although they are uncommon enough, and it is simple enough to make mistakes that the general recommendation is to prefer overloads to specializations.
When the caller explicitly requests the use of a template. In the code example you provide if the call is f<int>(42) or even f<42>(), then the overload will not be used.
When you cannot provide the required overloads, or the overload cannot be resolved at the place of call. For example if the type is not one of the function arguments (it is either not present in the signature at all or only in the return type:
template
T f();
In this case, you cannot provide overloads int f(); and double f(); but you can provide as many template specializations as you need, and it will be up to the user to force the selection of one or the other. Note that this could be considered a subcase of the previous case: because the template arguments take no part in the function arguments, the user needs to provide the template arguments, so the call is explicitly to a template.
When you want to place special constraints on the combination of arguments and inhibit implicit conversions:
template
void f( T, T ); // Both argument must be the same type
Because template argument deduction only perform perfect matches, this template can only be used when both arguments are of the exact same type, if you add an overload void f(int,int) that overload can be used with any combination of types that are implicitly convertible to int, like f( 5, 3.0 ), but the specialization won't.
In general, for most cases, none of the cases above really apply, so an overload should be preferred.
There might be more, but those are the ones I can recall off the top of my head
The way you declare the function does matter if you insist on calling it like f<int>(42). This will find the specialization, but not the overload.
If the call always looks like f(42), either alternative will work.
Function template specialization is deprecated in favor of function overloads with one exception: you are allowed to add a function template specialization to the std namespace, you aren't allowed to add a new function. So, if you need to supply a specific version for something in the std namespace, you have to use template specialization. For instance, to support creating an unordered_map with a user-defined class as the key you have to specialize std::hash for your class.
Suppose I have a function template where the type parameter is used as a return type only:
template <typename T>
T foo()
{
return whatever;
}
Then what is the correct syntax to specialize that function template? Both of the following seem to work:
template <>
std::string foo()
{
return whatever;
}
template <>
std::string foo<std::string>()
{
return whatever;
}
Is there any difference between the two? If not, what is the idiomatic way?
The compiler will deduce the correct template specialization based on informations provided (here, the function return type).
So these syntaxes have exactly the same behaviour, one being more explicit than the other.
In most case, there is no difference between the two.
If you overload several template functions, the second form may be needed to remove an ambiguity about which overload you mean to specialize (you probably have other problems if you are in this situation, for instance you'll also need to be explicit at call places).
Learning C++, came upon function templates. The chapter mentioned template specialization.
template <> void foo<int>(int);
void foo( int );
Why specialize when you can use the second? I thought templates were suppose to generalize. What's the point of specializing a function for a specific data type when you can just use a regular function?
Obviously, template specialization exists for a reason. When should it be used? I read Sutter's "Why not Specialize..." article but I need more of a layman's version since I'm just learning this stuff.
The main difference is that in the first case you are providing the compiler with an implementation for the particular type, while in the second you are providing an unrelated non-templated function.
If you always let the compiler infer the types, non-templated functions will be preferred by the compiler over a template, and the compiler will call the free function instead of the template, so providing a non-templated function that matches the arguments will have the same effect of specializations in most cases.
On the other hand, if at any place you provide the template argument (instead of letting the compiler infer), then it will just call the generic template and probably produce unexpected results:
template <typename T> void f(T) {
std::cout << "generic" << std::endl;
}
void f(int) {
std::cout << "f(int)" << std::endl;
}
int main() {
int x = 0;
double d = 0.0;
f(d); // generic
f(x); // f(int)
f<int>(x); // generic !! maybe not what you want
f<int>(d); // generic (same as above)
}
If you had provided an specialization for int of the template, the last two calls would call that specialization and not the generic template.
I personally can see no benefit from specializing a function template. Overloading it by either a different function template or a non-template function is arguably superior because its handling is more intuitive and it's overall more powerful (effectively by overloading the template, you have a partial specialization of the template, even though technically it's called partial ordering).
Herb Sutter has written an article Why not specialize function templates? where he discourages specializing function templates in favour of either overloading them or writing them so that they just forward to a class template's static function and specializing the class template instead.
You can use specialization when you know for a specific class the generic method could be efficient.
template<typename T>
void MySwap(T& lhs, T& rhs)
{
T tmp(lhs);
lhs = rhs;
rhs = tmp;
}
Now for vectors my swap will work, but is not very effecient. But I also know that std::vector implements its own swap() method.
template<>
void MySwap(std::vector<int>& lhs,std::vector<int>& rhs)
{
lhs.swap(rhs);
}
Please don;t compare to std::swap which is a lot more complex and better written. This is just an example to show that a generic version of MySwap() will work but is may not always be efficient. As a result I have shown how it can be made more efficient with a very specific template specialization.
We can also of course use overloading to achieve the same effect.
void MySwap(std::vector<int>& lhs,std::vector<int>& rhs)
{
lhs.swap(rhs);
}
So the question if why use template specialization (if one can use overloading). Why indeed. A non template function will always be chosen over a template function. So template specialization rules are not even invoked (which makes life a lot simpler as those rules are bizarre if you are not a lawyer as well as a computer programmer). So let me thing a second. No can't think of a good reason.
I find it very important. You can use this as you would use a virtual method. There would be no point in virtual methods unless some of them were specialized. I have used it a lot to differentiate between simple types (int,short,float) and objects, object pointers and object references.
An example would be serialize/unserialize methods that would handle objects by calling the objects serialize/unserialize method, while simple types should be written directly to a stream.
One case for template specialization which is not possible with overloading is for template meta-programming. The following is real code from a library that provides some of it services at compile time.
namespace internal{namespace os{
template <class Os> std::ostream& get();
struct stdout{};
struct stderr{};
template <> inline std::ostream& get<stdout>() { return std::cout; }
template <> inline std::ostream& get<stderr>() { return std::cerr; }
}}
// define a specialization for os::get()
#define DEFINE_FILE(ofs_name,filename)\
namespace internal{namespace os{ \
struct ofs_name{ \
std::ofstream ofs; \
ofs_name(){ ofs.open(filename);} \
~ofs_name(){ ofs.close(); delete this; } \
}; \
template <> inline std::ostream& get<ofs_name>(){ return (new ofs_name())->ofs; } \
}} \
using internal::os::ofs_name;
Multiple overloads on the same name do similar things. Specializations do the exact same thing, but on different types. Overloads have the same name, but may be defined in different scopes. A template is declared in only one scope, and the location of a specialization declaration is insignificant (although it must be at the scope of the enclosing namespace).
For example, if you extend std::swap to support your type, you must do so by specialization, because the function is named std::swap, not simply swap, and the functions in <algorithm> would be quite right to specifically call it as ::std::swap( a, b );. Likewise for any name that might be aliased across namespaces: calling a function may get "harder" once you qualify the name.
The scoping issue is confused further by argument-dependent lookup. Often an overload may be found because it is defined in proximity to the type of one of its arguments. (For example, as a static member function.) This is completely different from how the template specialization would be found, which is by simply looking up the template name, and then looking up the explicit specialization once the template has been chosen as the target of the call.
The rules of ADL are the most confusing part of the standard, so I prefer explicit specialization on the priciple of avoiding reliance on it.