Templates Default Arguments not working in C++ - c++

#include <iostream>
template<typename T = char>
T cast(T in){
return in;
}
int main(){
std::cout << cast<>(5) << std::endl;
return 0;
}
Above will print 5 instead of an empty character, as the function is supposed to return a character by default and not an int. What am I ding wrong?
Edit:
Forcing it with std::cout << cast<char>(5) << std::endl; shows an empty character.

The declaration of 5 is an integer by default. This causes 'T' to be overridden with the type int, rather than using your default type. If you really wanted the char of value 5 (which you probably don't), you could specify it as '\x5'.
For the ascii character 5....
int main(){
std::cout << cast('5') << std::endl;
return 0;
}
Default types in templates tend to be useful when it's not easy to determine the template type, e.g. cast from int
template<typename T = char>
T cast(int v){
return T(v);
}
and now this will default to a method that casts an int to a char (rather than a int to int).
std::cout << cast(53) << std::endl;

Related

Types should be the same but are not

I am not sure I understand why the first test evaluates to true and the second to false. I know that the information from typeid().name() is usually not reliable, but my main problem is with the typeid itself. I don't understand why the type of *test is not Location<1>, or what else is wrong. Any thoughts? Is there same wrapper around a type here that I don't see? Thanks in advance, and apologies if the answer is obvious.
#include <iostream>
#include <utility>
#include <typeinfo>
class LocationAbstract
{
virtual void get_() = 0;
};
template<int i>
class Location : public LocationAbstract
{
public:
static constexpr int test = i;
virtual void get_() override
{
return;
}
};
template <int i>
Location<i> LocationGenerator()
{
Location<i> test{};
return test;
}
int main()
{
LocationAbstract *table[10];
table[0] = new decltype(LocationGenerator<0>());
table[1] = new decltype(LocationGenerator<1>());
Location<1> *test;
try
{
std::cout << "Casting\n";
test = dynamic_cast<Location<1>*>(table[1]);
}
catch (std::bad_cast &e)
{
std::cout << "Bad cast\n";
}
// test1, evaluates to true
std::cout << (typeid(*test) == typeid(*dynamic_cast<Location<1>*>(table[1]))) << "\n";
std::cout << typeid(*test).name() << "\n";
std::cout << typeid(*dynamic_cast<Location<1>*>(table[1])).name() << "\n----\n";
// test2, why does this evaluate to false while the above evaluates to true ?
std::cout << (typeid(Location<1>()) == typeid(*dynamic_cast<Location<1>*>(table[1]))) << "\n";
std::cout << typeid((Location<1>())).name() << "\n";
std::cout << typeid(*dynamic_cast<Location<1>*>(table[1])).name() << "\n";
auto test1 = Location<1>();
auto test2 = *dynamic_cast<Location<1>*>(table[1]);
std::cout << typeid(test1).name() << " and " << typeid(test2).name() << "\n";
return 0;
}
An extra set of () makes all the difference here. In typeid(Location<1>()) and typeid((Location<1>())), Location<1>() actually means two totally different things.
In typeid(Location<1>()), Location<1>() is interpreted as a function type that returns a Location<1> and takes no parameters.
In typeid((Location<1>())), Location<1>() is interpreted as value-initializing an anonymous Location<1> object.
The typeid operator can work on either types or expressions. That is, you can say typeid(int) as well as typeid(42). Since Location<1>() can be interpreted as a type, the language does so. (Location<1>()) cannot be interpreted as a type though, so it must be interpreted as an expression. The only thing Location<1>() can mean as part of an expression is to value-initialize an anonymous Location<1> object, so typeid gives you the type of that object.
Let this be yet another reason to prefer uniform-initialization syntax when creating temporary objects; Location<1>{} would not have this ambiguity.
Examine these two lines:
std::cout << (typeid(Location<1>()) == typeid(*dynamic_cast<Location<1>*>(table[1]))) << "\n";
std::cout << typeid((Location<1>())).name() << "\n";
In the first line, you use typeid(Location<1>()). typeid can take types as well as expressions, and Location<1>() is a function type with no parameters and a return type of Location<1>.
So why does the name print the same? That's because of the second line: typeid((Location<1>())). By wrapping the argument in parentheses, it is no longer a valid type, so it is treated as an expression and the name of typeid(Location<1>) is printed. Removing the extra parentheses prints F8LocationILi1EEvE under the same mangling scheme.
To avoid the ambiguity, you can also use the type directly (typeid(Location<1>)) or use braces: typeid(Location<1>{})).

Get the size of the return type of a member function

I have classes/structs with member functions. I want to check that the return type has the correct size.
#include <iostream>
#include <type_traits>
struct QString {
wchar_t ucs2() {return L"1"[0];}
};
int main() {
QString arg;
std::cout << "wchar_t " << sizeof(wchar_t) << std::endl;
std::cout << "std::invoke_result_t<decltype(&QString::ucs2)(void)> " << sizeof(std::invoke_result_t<decltype(&QString::ucs2)(void)>) << std::endl;
}
Result is, for example,
wchar_t 4
std::invoke_result_t<decltype(&QString::ucs2)(void)> 16
so I get different sizes. I expected std::invoke_result_t<decltype(&QString::ucs2)(void) to be the return type of my ucs2 function, i.e. wchar_t, but it doesn't seem to be the case. What is going on here?
invoke_result is defined as:
template< class F, class... ArgTypes>
class invoke_result;
Hence, this is working
return sizeof(std::invoke_result_t<decltype(&QString::ucs2), QString>);
A simpler solution:
int main() {
std::cout << sizeof(QString().ucs2()) << '\n';
return 0;
}
The QString() default constructs a QString, which can then be used to call ucs2. But since this all happens as an operand to sizeof, nothing is actually constructed or called. The compiler does all the type analysis at compile time, even without enabling optimizations.
Obviously, if you can't default construct the class, this may be less useful.

Return type deduction from bytes to fundamental types [duplicate]

This might be a silly question but I would like to have it clarified none the less. Lets say I have a template function like so:
template<class T> T getValue(const char *key) const;
that returns the value as T from internal storage where it is stored under key (and possibly as type T already).
Now in order to use this I need to specify the template return type T in the function call, for example:
int value = getValue<int>("myKey");
while what I would want it to do is deduce the template argument from the context, specifically the lvalue like so:
int value = getValue("myKey"); //getValue<int>() is instantiated with int being deduced automatically from lvalue
but I am guessing that this is not possible but I am rather fuzzy as to why. I know using auto would make it impossible for the compiler to deduce the template type but why this is as well?
Template instantiation can only deduce its parameters from the arguments to given templated object(function in this case) so no, the variable type does not matter in deducing, and you either have to provide dummy argument of type T to the function or hardcode it as you did in the second to last script code(getValue<int>(...)).
There is a possible workaround using type deduction presented in the comments :
#include <iostream>
namespace byte_read {
//this is a hack to deduce the type using implicit conversion
struct type_converter {
const char* buffer;
template<typename T>
operator T() {
std::cout << "implicit convertion from " << typeid(buffer).name()
<< " to " << typeid(T).name() << std::endl;
//casting memory to the desired type
return static_cast<T>(*buffer);
}
};
type_converter getValue(const char * buffer) {
//here buffer is implicitly converted to T type using the operator T()
return {buffer};
}
}
using namespace byte_read;
int main()
{
char buffer[]{0,1,0,0 //int 256 encoded
,97 //char 'a' encoded
};
//pointer to read the buffer sequentialy
char* pos = buffer;
//pointer used to count the bytes readed
char* last_pos = pos;
int int_256 = getValue(pos);
pos+=sizeof(int);
std::cout << int_256 << " bytes readed :" << pos - last_pos << std::endl;
last_pos = pos;
char char_a = getValue(pos);
pos+=sizeof(char);
std::cout << char_a << " bytes readed :" << pos - last_pos << std::endl;
}
You can try it here

Template return type deduction from lvalue?

This might be a silly question but I would like to have it clarified none the less. Lets say I have a template function like so:
template<class T> T getValue(const char *key) const;
that returns the value as T from internal storage where it is stored under key (and possibly as type T already).
Now in order to use this I need to specify the template return type T in the function call, for example:
int value = getValue<int>("myKey");
while what I would want it to do is deduce the template argument from the context, specifically the lvalue like so:
int value = getValue("myKey"); //getValue<int>() is instantiated with int being deduced automatically from lvalue
but I am guessing that this is not possible but I am rather fuzzy as to why. I know using auto would make it impossible for the compiler to deduce the template type but why this is as well?
Template instantiation can only deduce its parameters from the arguments to given templated object(function in this case) so no, the variable type does not matter in deducing, and you either have to provide dummy argument of type T to the function or hardcode it as you did in the second to last script code(getValue<int>(...)).
There is a possible workaround using type deduction presented in the comments :
#include <iostream>
namespace byte_read {
//this is a hack to deduce the type using implicit conversion
struct type_converter {
const char* buffer;
template<typename T>
operator T() {
std::cout << "implicit convertion from " << typeid(buffer).name()
<< " to " << typeid(T).name() << std::endl;
//casting memory to the desired type
return static_cast<T>(*buffer);
}
};
type_converter getValue(const char * buffer) {
//here buffer is implicitly converted to T type using the operator T()
return {buffer};
}
}
using namespace byte_read;
int main()
{
char buffer[]{0,1,0,0 //int 256 encoded
,97 //char 'a' encoded
};
//pointer to read the buffer sequentialy
char* pos = buffer;
//pointer used to count the bytes readed
char* last_pos = pos;
int int_256 = getValue(pos);
pos+=sizeof(int);
std::cout << int_256 << " bytes readed :" << pos - last_pos << std::endl;
last_pos = pos;
char char_a = getValue(pos);
pos+=sizeof(char);
std::cout << char_a << " bytes readed :" << pos - last_pos << std::endl;
}
You can try it here

Initialize only first argument of c++11 tuple

Minimal working example:
#include <tuple>
struct example
{
example(int, char) {}
};
int main()
{
std::tuple<example, int, double>
my_tuple(example(0, 'x'), 42, .0);
// std::tuple t = make_my_tuple(0, 'x');
return 0;
}
This works.
Is there a more elegant way to initialize only the first member, like I sketched in the comment? One which only takes the arguments to construct the first tuple member and does not initialize the others?
The reason I ask? I am just interested in the semantics of the language.
You say that giving values for the other two members is not necessary - are you worried about performance? Or that there may be no suitable value for these members?
If it's the latter, you could have your tuple hold boost::optionals. e.g.
#include <tuple>
#include <boost/optional.hpp>
using namespace boost;
struct example
{
example(int, char) {}
};
typedef std::tuple<example, optional<int>, optional<double>> MyTuple;
int main()
{
MyTuple my_tuple(example(0, 'x'), optional<int>(), optional<double>());
return 0;
}
You now semantically have the int and float "uninitialised", and can query their value as such.
To make this more elegant, you can wrap this into a function, using the perfect forwarding idiom for the arguments (in general; in this case your arguments are cheap to copy, so no speed benefit from doing this):
template <class... Args>
MyTuple make_mytuple(Args&&... args)
{
return MyTuple(example(std::forward<Args>(args)...), optional<int>(), optional<double));
}
The advantage of this template is that it's resilient to changes in example's constructor. If you add another argument, just call make_mytuple with the new arguments and it will work.
Your other point about the copying in the tuple construction is valid, but in reality I believe this will be optimal on most compilers. (a combination of RVO and elision of copies when passing an rvalue to a function by value).
You can use uniform initialization. Sadly, you cannot define a default value, argument will be initialized with the default constructor or 0.
#include <iostream>
#include <tuple>
enum class Result {Full, Partial, Empty};
std::tuple<bool, int, double> get_tuple(Result type)
{
if (type == Result::Full)
return {true, 42, 3.14159};
else if (type == Result::Partial)
return {true, 42, {}};
else
return {};
}
int main()
{
bool b;
int i;
double d;
std::tie(b, i, d) = get_tuple(Result::Full);
std::cout << b << " " << i << " " << d << std::endl;
std::tie(b, i, d) = get_tuple(Result::Partial);
std::cout << b << " " << i << " " << d << std::endl;
std::tie(b, i, d) = get_tuple(Result::Empty);
std::cout << b << " " << i << " " << d << std::endl;
return 0;
}
output:
1 42 3.14159
1 42 0
0 0 0