My std::hash for std::tuples... Any improvements? [closed] - c++

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Some may have noticed that std::hash does not support tuples. So I added an overload which just seems "nicer" than the solution I saw up till now. Anyone got ideas to further cut down this code? Please note that this is a compiler killer! The only one that could compile it was "Clang 3.2"... Intel Compiler 13.1 does not get the specialization and keeps telling "C++ standard does not support hash blabla". And we don't need to talk about the original Microsoft compiler do we.
BTW, my solution supports recursive tuples like std::tuple<std::tuple<int,int>,int> so I am not sure if this also applies to the existing solutions I saw this day.
namespace std
{
template<typename... TTypes>
class hash<std::tuple<TTypes...>>
{
private:
typedef std::tuple<TTypes...> Tuple;
template<int N>
size_t operator()(Tuple value) const { return 0; }
template<int N, typename THead, typename... TTail>
size_t operator()(Tuple value) const
{
constexpr int Index = N - sizeof...(TTail) - 1;
return hash<THead>()(std::get<Index>(value)) ^ operator()<N, TTail...>(value);
}
public:
size_t operator()(Tuple value) const
{
return operator()<sizeof...(TTypes), TTypes...>(value);
}
};
}

Quite obvious once you've seen it:
template<int N, typename THead, typename... TTail>
size_t operator()(Tuple value) const
{
constexpr int Index = N - sizeof...(TTail) - 1;
return hash<THead>()(std::get<Index>(value)) ^ operator()<N, TTail...>(value);
}

Related

C++ constexpr function parameters [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 months ago.
Improve this question
With this nice simplified compile time string class.
There are no constexpr/consteval function parameters in C++
but the point of this question is:
Can I get a function call style for passing of non-type template parameters ?
With the suffix I can get pretty close.
But can it be done better ?
I do not want to use this syntax
test_normal_function2<"asd">(x);
How can I get rid of _fs suffix in the invocation of test_normal_function ?
#include <algorithm>
struct no_init_fixed_string {};
template <std::size_t N>
struct fixed_string
{
constexpr fixed_string(const char (&foo)[N + 1])
{
std::copy_n(foo, N + 1, data.begin());
}
std::array<char, N + 1> data{};
constexpr fixed_string(no_init_fixed_string)
: data{}
{
}
};
template <std::size_t N>
fixed_string(const char (&str)[N]) -> fixed_string<N - 1>;
template<fixed_string s>
struct fixed_string_type
{
};
template<fixed_string s>
constexpr auto operator"" _fs()
{
return fixed_string_type<s>{};
}
template<fixed_string s>
void test_normal_function(fixed_string_type<s>, int x )
{
//use s as consexpr parameter
}
template<fixed_string s>
void test_normal_function2( int x )
{
}
int main()
{
int x = 3;
test_normal_function("asd"_fs,x); //this works
test_normal_function2<"asd">(x); // this works but its ugly
//test_normal_function("asd",x); //this doesn't compile but its pretty.
}
How can I make call to test_normal_function work without _fs suffix ?
Preprocessor macro trickery aside, it is impossible to do it with the exact syntax you want, because a usual string literal (not a user-defined literal) does never encode its value in its type (only its length).
A value passed to a function via a function parameter can never be used by the function in a constant expression. Only information in the type can be used that way.
However, you can pass a value via a template parameter and make use of it in a constant expression:
test_normal_function<"asd">({},x);

how to use static assert to check custom datatype in template [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I have a class MyClass.
Now, I want to write a function which will return either a unique_ptr or a shared_ptr depending on how a function is called like this:
using MyClassUnique = std::unique_ptr<MyClass>;
using MyClassShared = std::shared_ptr<MyClass>;
template<typename T>
T createMyClass(int x)
{
static_assert(std::is_same<T, MyClassUnique >::value ||
std::is_same<T, MyClassShared >::value, "Not a matching type");
return T(new MyClass(x));
}
And while using, I will use it like this:
int ptr = createMyClass<int>(5); //throws compilation error "Not a matching type"
MyClassUnique ptr = createMyClass<MyClassUnique>(5); //works file
Is there a better way of doing this?
std::unique_ptr ptr = std::unique_ptr(new MyClass(5));
This is not allowed due to some constraint.
In C++20 with you could use a concept:
template<class T>
concept MyClassUniqueOrShared = std::same_as<T, MyClassUnique> || std::same_as<T, MyClassShared>;
template<MyClassUniqueOrShared T>
T createMyClass(int x) {
return T(new MyClass(x));
}
You could use SFINAE:
template<typename T>
typename std::enable_if<std::is_same_v<T, MyClassUnique> || std::is_same_v<T, MyClassShared>, T>::type
createMyClass(int x) {
return T(new MyClass(x));
}
If you have C++17 you can use if constexpr like this:
#include <iostream>
#include <memory>
template<class> inline constexpr bool always_false_v = false;
struct MyClassUnique
{
MyClassUnique(int n) {}
};
struct MyClassShared
{
MyClassShared(int n) {}
};
template<typename T>
auto createMyClass(int n)
{
if constexpr(std::is_same_v<T, MyClassUnique>)
{
return std::make_unique<T>(n);
}
else if constexpr(std::is_same_v<T, MyClassShared>)
{
return std::make_shared<T>(n);
}
else
{
static_assert(always_false_v<T>, "Invalid template parameter");
}
}
int main()
{
auto a = createMyClass<MyClassUnique>(1);
auto b = createMyClass<MyClassShared>(1);
return 0;
}
Demo
Note you can use std::make_unique and std::make_shared this way which are better than using using new.

How to return a type from C++ functions? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'm reading C++ Templates: The Complete Guide, 2th Edition, And i see this code:
template<typename T1, typename T2>
std::common_type_t<T1, T2> max (T1 a, T2 b)
{
return b < a ? a : b;
}
According to what I've read from page 12, I want to ask how function figures the type it wants to return? In the above example, how max function figures the type it wants to return, choosing between T1 and T2?
I looked in : ./gcc/libstdc++-v3/include/std/type_traits:2115 but could not figure out what happened.
WHAT I WANT TO DO:
I have a lot of typedefed function pointer like this:
typedef void (*voidVoid)();
typedef void (*voidInt)(int);
typedef void (*voidDouble)(double);
...
And i want to make a function like:
Type getFunctionPointer(const std::string& name);
Which take name of function-pointer and return corresponding function-pointer. Before I find templates I thought it's not possible. But I think, std::commone_type_t is exactly doing what I want to do. It take a variable and return a type (Which is type of that variable).
How can I define that? Can I implement it with std::commone_type_t or a better solution, just with templates?
Your question does not make sense. This function:
template<typename T1, typename T2>
std::common_type_t<T1, T2> max (T1 a, T2 b)
{
return b < a ? a : b;
}
does not return the type std::common_type_t<T1, T2>. It returns a value (either a or b), and the type of the value is std::common_type_t<T1, T2>.
In the same way, this function:
int max2 (int a, int b)
{
return b < a ? a : b;
}
returns a value of type int, but does not return the type int itself.
If you want to write a function that returns a value of another type, for example std::string, you write it before the function name:
vvvvvvvvvvv here
std::string return_a_string ()
{
return "hello";
}

Compile time static array of types [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'm trying to build a static array of dynamic arrays...at compile time. Some examples:
struct Apple {
int x;
};
struct Pear {
int a, b;
};
then...
Registry<Apple, Pear> registry;
auto appleId = registry.add<Apple>(1);
auto pearId = registry.add<Pear>(1, 2);
Apple* apple = registry.get<Apple>(appleId);
or...
Registry registry;
registry.register<Apple>();
registry.register<Pear>();
...although the second example would probably be even harder to do at compile time.
I would assume that the data structure inside looks like this:
template <typename... Ts>
struct Registry {
std::array<std::vector<?>, sizeof...(Ts)> values;
};
Any ideas on how to start exploring this problem?
std::vector can only contain elements of the same type. std::tuple, on the other hand, can contain elements of different types:
template<typename... Ts>
struct Registry {
std::tuple<std::vector<Ts>...> values;
template<class T, class... Args>
size_t add(Args&&... args) {
auto& v = std::get<std::vector<T>>(values);
auto idx = v.size();
v.emplace_back(std::forward<Args>(args)...);
return idx;
}
template<class T>
T* get(size_t idx) {
auto& v = std::get<std::vector<T>>(values);
return idx < v.size() ? &v[idx] : 0;
}
};
int main() {
Registry<Apple, Pear> registry;
auto appleId = registry.add<Apple>(1);
auto pearId = registry.add<Pear>(1, 2);
Apple* apple = registry.get<Apple>(appleId);
}
However, manipulating such Registry in C++17 is run-time only.

Why is this telling me thehash2 is not a template? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I'm very confused as to why Terminal is telling me that thehash2 is not a template when I try to compile.
Am I crazy?
template<typename Symbol>
class thehash
{
public:
size_t operator()(const Symbol & item)
{
static thehash2<string> hf;
return hf(item.getData());
}
};
template<typename string>
class thehash2<string>
{
public:
size_t operator()(const string & key)
{
size_t hashVal = 0;
for(char ch : key)
hashVal = 37 * hashVal + ch;
return hashVal;
}
};
template<typename string>
class thehash2<string>
{
Here's an error. You might wanted to write:
template<typename T>
class thehash2
{
Note, that - as stated in comments - you shouldn't use string as a typename in template. Most common names for template parameters are usually single letters - T, U, ... such that they won't be easily confused with real type names.
Second option:
class thehash2 : public thehash<std::string>
{
(depending on your actual needs)