for Debugging purposes I'd like to extract the name of the function from a template argument. However I'm only getting the functions signature not an actual name.
namespace internal
{
static const unsigned int FRONT_SIZE = sizeof("internal::GetTypeNameHelper<") - 1u;
static const unsigned int BACK_SIZE = sizeof(">::GetTypeName") - 1u;
template<typename T>
struct GetTypeNameHelper
{
static const char* GetTypeName(void)
{
#ifdef __GNUC__
static const size_t size = sizeof(__PRETTY_FUNCTION__);
static char typeName[size] = { };
memcpy(typeName, __PRETTY_FUNCTION__, size - 1u);
#else
static const size_t size = sizeof(__FUNCTION__) - FRONT_SIZE - BACK_SIZE;
static char typeName[size] =
{};
memcpy(typeName, __FUNCTION__ + FRONT_SIZE, size - 1u);
#endif //__GNUC__
return typeName;
}
};
} //namespace internal
template<typename T>
const char* GetTypeName(void)
{
return internal::GetTypeNameHelper<T>::GetTypeName();
}
Calling this from an own make function
template<typename Func_T, typename ... Args>
CExtended_Function<Args...> Make_Extended_Function(Func_T f)
{
std::function<void(Args...)> func(f);
const char* pFunc_Name = NCommonFunctions::GetTypeName<Func_T>();
CExtended_Function<Args...> res(f, func_name);
return res;
}
with
void Test_Func();
void foo()
{
Make_Extended_Function(Test_Func);
}
Gives me only the function signature.
... [with T = void (*)()]...
However I'd like to get the function name (in this case "Test_Func")
I thought about using makros but I'm not sure how to implement the Args... Part in Makros. Do you have an idea on how to solve this? I'd like to avoid using RTTI.
Functions aren't valid template arguments - your template argument here is the type of a pointer to the function, not the function itself - so this is completely impossible. There is also no portable way to get the name of a particular function at compile time either, at least at the moment (it's possible that this will be possible in the future through compile time reflection, but that's going to be C++2y (23?) at the earliest).
With Macro, you can do (I also use CTAD from C++17)
template<typename F>
auto Make_Extended_Function_Impl(F f, const std::string& name)
{
std::function func(f);
CExtended_Function res(f, name);
return res;
}
#define Make_Extended_Function(f) Make_Extended_Function(f, #f)
Related
I want to write a function that extracts a pointer field from a struct. The requirement is that if I pass the struct as a const argument, the returned type should be const. If not, the returned type should not be const.
For instance,
struct S {
char *p;
};
// approach 1: two overload functions with duplicate body
auto extract(S &input) -> int * {
return reinterpret_cast<int *>(input.p + 12);
}
auto extract(const S &input) -> const int * {
return reinterpret_cast<const int *>(input.p + 12);
}
// approach 2: macro
#define macro_extract(input) (reinterpret_cast<int *>(input.p + 12))
Is there any trick in template or latest C++ standard that can write a strongly typed function without duplicating the body?
EDIT:
Changed the example a bit to reflect more accurately of the real problem.
Here's a solution with a single function template:
template<typename T,
typename = std::enable_if_t<
std::is_same_v<
std::remove_cv_t<
std::remove_reference_t<T>>, S>>>
auto extract(T&& input)
-> std::conditional_t<
std::is_const_v<
std::remove_reference_t<T>>, int const *, int *>
{
return input.p;
}
Here's a demo.
I think it goes without saying that you'd be better off with an overload set. If the function body is large, you can still call the non-const version from the const overload, and add the const there.
if constexpr and auto as return type solution:
#include <type_traits>
struct S {
int *p;
};
template<typename T>
auto extract(T &&input) {
static_assert(std::is_same_v<std::decay_t<decltype(input)>,S>, , "Only struct S is supported");
if constexpr(!std::is_const_v<std::remove_reference_t<decltype(input)>>) {
return input.p;
} else {
return const_cast<const int*>(input.p);
}
}
int main () {
S i;
using t = decltype(extract(i));
static_assert(std::is_same_v<t,int*>);
S const i_c{0};
using t_c = decltype(extract(i_c));
static_assert(std::is_same_v<t_c,const int*>);
return 0;
}
PLZ look at the ISO proposal:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4388.html
And the std::experimental::propagate_const spec:
https://en.cppreference.com/w/cpp/experimental/propagate_const
Or one can implement his own version of propagate_const.
have fun,
FM
SFINAE should be able to do this. The approximate format is:
template<class T,
class allow=std::enable_if_t<std::is_base_of_v<S, T>>>
auto extract(T&& input) -> decltype(input.p) {
return input.p;
}
Basically using universal forwarding references to make it work for anything: S, S&, const S&, S&&, volatile S&, etc.
Here is my code:
template<int... I>
class MetaString1
{
public:
constexpr MetaString1(constexpr char* str)
: buffer_{ encrypt(str[I])... } { }
const char* decrypt()
{
for (int i = 0; i < sizeof...(I); ++i)
buffer_[i] = decrypt1(buffer_[i]);
buffer_[sizeof...(I)] = 0;
return buffer_;
}
private:
constexpr char encrypt(constexpr char c) const { return c ^ 0x55; }
constexpr char decrypt1(constexpr char c) const { return encrypt(c); }
private:
char buffer_[sizeof...(I)+1];
};
#define OBFUSCATED1(str) (MetaString1<0, 1, 2, 3, 4, 5>(str).decrypt())
int main()
{
constexpr char *var = OBFUSCATED1("Post Malone");
std::cout << var << std::endl;
return 1;
}
This is the code from the paper that I'm reading Here. The Idea is simple, to XOR the argument of OBFUSCATED1 and then decrypt back to original value.
The problem that I'm having is that VS 2017 gives me error saying function call must have a constant value in constant expression.
If I only leave OBFUSCATED1("Post Malone");, I have no errors and program is run, but I've noticed that if I have breakpoints in constexpr MetaString1 constructor, the breakpoint is hit, which means that constexpr is not evaluated during compile time. As I understand it's because I don't "force" compiler to evaluate it during compilation by assigning the result to a constexpr variable.
So I have two questions:
Why do I have error function call must have a constant value in constant expression?
Why do people use template classes when they use constexpr functions? As I know template classes get evaluated during compilation, so using template class with constexpr is just a way to push compiler to evaluate those functions during compilation?
You try to assign a non constexpr type to a constexpr type variable,
what's not possible
constexpr char *var = OBFUSCATED1("Post Malone")
// ^^^ ^^^^^^^^^^^
// type of var is constexpr, return type of OBFUSCATED1 is const char*
The constexpr keyword was introduced in C++11, so before you had this keyword you had to write complicated TMP stuff to make the compiler do stuff at compile time. Since TMP is turing complete you theoretically don't need something more than TMP, but since TMP is slow to compile and ugly to ready, you are able to use constexpr to express things you want evaluate at compile time in a more readable way. Although there is no correlation between TMP and constexpr, what means, you are free to use constexpr without template classes.
To achieve what you want, you could save both versions of the string:
template <class T>
constexpr T encrypt(T l, T r)
{
return l ^ r;
}
template <std::size_t S, class U>
struct in;
template <std::size_t S, std::size_t... I>
struct in<S, std::index_sequence<I...>>
{
constexpr in(const char str[S])
: str_{str[I]...}
, enc_{encrypt(str[I], char{0x12})...}
{}
constexpr const char* dec() const
{
return str_;
}
constexpr const char* enc() const
{
return enc_;
}
protected:
char str_[S];
char enc_[S];
};
template <std::size_t S>
class MetaString1
: public in<S, std::make_index_sequence<S - 1>>
{
public:
using base1_t = in<S, std::make_index_sequence<S - 1>>;
using base1_t::base1_t;
constexpr MetaString1(const char str[S])
: base1_t{str}
{}
};
And use it like this:
int main()
{
constexpr char str[] = "asdffasegeasf";
constexpr MetaString1<sizeof(str)> enc{str};
std::cout << enc.dec() << std::endl;
std::cout << enc.enc() << std::endl;
}
Suppose we have a function that looks like:
template <typename F, typename... A>
inline void execute(F&& functor, A&& ... args) {
std::forward<decltype(functor)>(functor)(std::forward<decltype(args)>(args)...);
}
This works for simple non-templated functions. However, I am trying to perfect-forward a templated function(a quite contrived one):
namespace detail {
template <typename CodecImpl>
class codec
{
public:
//
// Encoding
// Convenient version, returns an std::string.
static std::string encode(const uint8_t* binary, size_t binary_size);
static std::string encode(const char* binary, size_t binary_size);
...
};
class base64_rfc4648
{
public:
template <typename Codec> using codec_impl = stream_codec<Codec, base64_rfc4648>;
static CPPCODEC_ALWAYS_INLINE constexpr size_t alphabet_size() {
static_assert(sizeof(base64_rfc4648_alphabet) == 64, "base64 alphabet must have 64 values");
return sizeof(base64_rfc4648_alphabet);
}
static CPPCODEC_ALWAYS_INLINE constexpr char symbol(alphabet_index_t idx)
{
return base64_rfc4648_alphabet[idx];
}
...
};
} // namespace detail
using base64_rfc4648 = detail::codec<detail::base64<detail::base64_rfc4648>>;
Trying to forward the above:
std::string buf("hello world");
execute(base64_rfc4648::encode, buf.c_str(), buf.size());
Does not work. Template deduction fails:
note: couldn't deduce template parameter 'F'
and it also notes:
No matching function for call to 'execute(<unresolved overloaded function type>, const char*, std::__cxx11::basic_string<char>::size_type)'
How can I fix this?
NOTE: I kept the information short above for readability, but if more info is needed I can add.
I have created a MCVE to work on the problem, rather than the code.
So let us have a generic function called print() which we want to send to your execute()
template <typename Arg>
inline void print(Arg const & a) {
std::cout << a << std::endl;
}
where execute() is:
template <typename F, typename... A>
inline void execute(F&& functor, A&& ... args) {
std::forward<decltype(functor)>(functor)(std::forward<decltype(args)>(args)...);
}
When we try to call execute(print, 10) it fails.
The problem is that the execute() function doesn't understand which overload of print are we trying to call.
Now this problem can be solved in 2 ways :
First approach, specify the complete type of the templated function :
execute(print<int>, 10);
Second approach, create a helper function.
Every problem can be solved by adding one more layer.
This helper function will help us deduce the types, before we pass it to execute()
template <typename Arg>
inline void execute_print(Arg const & a) {
execute(print<Arg>, a); // we need to specify which overload to be invoked
}
And then you can call : execute_print(20);
Here is a full working code for your reference(compiled using C++11):
#include <string>
#include <iostream>
template <typename Arg>
inline void print(Arg const & a) {
std::cout << a << std::endl;
}
template <typename F, typename... A>
inline void execute(F&& functor, A&& ... args) {
std::forward<decltype(functor)>(functor)(std::forward<decltype(args)>(args)...);
}
template <typename Arg>
inline void execute_print(Arg const & a) {
execute(print<Arg>, a); // we need to specify which overload to be invoked
}
int main() {
// execute(print, 5); // wont compile
execute(print<int>, 10);
execute_print(20);
return 0;
}
You can simply use boost::hof to wrap base64_rfc4648::encode in a function object.
execute(BOOST_HOF_LIFT(base64_rfc4648::encode), buf.c_str(), buf.size());
Here is the doc of BOOST_HOF_LIFT
As stated in this link:
There is no specialization for C strings. std::hash produces a hash of the value of the pointer (the memory address), it does not examine the contents of any character array.
Which means that with the same char* value, different hashcodes could be produced. For example, having this code:
//MOK and MOV are template arguments
void emit(MOK key, MOV value) {
auto h = hash<MOK>()(key);
cout<<"key="<<key<<" h="<<h<<endl;
...
This is the output produced by calling 4 times emit() on the same key (with MOK=char*) value (but 4 different tokens/string objects):
key=hello h=140311481289184
key=hello h=140311414180320
key=hello h=140311414180326
key=hello h=140311481289190
How can I obtain the same hash code for char*? I'd prefer not to use boost
There is of course the trivial (and slow) solution of creating a temporary std::string and hashing that one. If you don't want to do this, I'm afraid you will have to implement your own hash function. Sadly enough, the current C++ standard library doesn't provide general purpose hash algorithms disentangled from object-specific hash solutions. (But there is some hope this could change in the future.)
Suppose you had a function
std::size_t
hash_bytes(const void * data, std::size_t size) noexcept;
that would take an address and a size and return you a hash computed from the that many bytes following that address. With the help of that function, you could easily write
template <typename T>
struct myhash
{
std::size_t
operator()(const T& obj) const noexcept
{
// Fallback implementation.
auto hashfn = std::hash<T> {};
return hashfn(obj);
}
};
and then specialize it for the types you're interested in.
template <>
struct myhash<std::string>
{
std::size_t
operator()(const std::string& s) const noexcept
{
return hash_bytes(s.data(), s.size());
}
};
template <>
struct myhash<const char *>
{
std::size_t
operator()(const char *const s) const noexcept
{
return hash_bytes(s, std::strlen(s));
}
};
This leaves you only with the exercise of implementing hash_bytes. Fortunately, there are some fairly good hash functions that are rather easy to implement. My go-to algorithm for simple hashing is the Fowler-Noll-Vo hash function. You can implement it in five lines of code; see the linked Wikipedia article.
If you want to get a bit fancy, consider the following implementation. First, I define a generic template that can be specialized for any version of the FNV-1a hash function.
template <typename ResultT, ResultT OffsetBasis, ResultT Prime>
class basic_fnv1a final
{
static_assert(std::is_unsigned<ResultT>::value, "need unsigned integer");
public:
using result_type = ResultT;
private:
result_type state_ {};
public:
constexpr
basic_fnv1a() noexcept : state_ {OffsetBasis}
{
}
constexpr void
update(const void *const data, const std::size_t size) noexcept
{
const auto cdata = static_cast<const unsigned char *>(data);
auto acc = this->state_;
for (auto i = std::size_t {}; i < size; ++i)
{
const auto next = std::size_t {cdata[i]};
acc = (acc ^ next) * Prime;
}
this->state_ = acc;
}
constexpr result_type
digest() const noexcept
{
return this->state_;
}
};
Next, I provide aliases for the 32 and 64 bit versions. The parameters were taken from Landon Curt Noll's website.
using fnv1a_32 = basic_fnv1a<std::uint32_t,
UINT32_C(2166136261),
UINT32_C(16777619)>;
using fnv1a_64 = basic_fnv1a<std::uint64_t,
UINT64_C(14695981039346656037),
UINT64_C(1099511628211)>;
Finally, I provide type meta-functions to select a version of the algorithm given the wanted number of bits.
template <std::size_t Bits>
struct fnv1a;
template <>
struct fnv1a<32>
{
using type = fnv1a_32;
};
template <>
struct fnv1a<64>
{
using type = fnv1a_64;
};
template <std::size_t Bits>
using fnv1a_t = typename fnv1a<Bits>::type;
And with that, we're good to go.
constexpr std::size_t
hash_bytes(const void *const data, const std::size_t size) noexcept
{
auto hashfn = fnv1a_t<CHAR_BIT * sizeof(std::size_t)> {};
hashfn.update(data, size);
return hashfn.digest();
}
Note how this code automatically adapts to platforms where std::size_t is 32 or 64 bits wide.
I've had to do this before and ended up writing a function to do this, with essentially the same implementation as Java's String hash function:
size_t hash_c_string(const char* p, size_t s) {
size_t result = 0;
const size_t prime = 31;
for (size_t i = 0; i < s; ++i) {
result = p[i] + (result * prime);
}
return result;
}
Mind you, this is NOT a cryptographically secure hash, but it is fast enough and yields good results.
In C++17 you should use std::hash<std::string_view> which works seamlessly since const char* can be implicitly converted to it.
Since C++17 added std::string_view including a std::hash specialization for it you can use that to compute the hash value of a C-string.
Example:
#include <string_view>
#include <cstring>
static size_t hash_cstr(const char *s)
{
return std::hash<std::string_view>()(std::string_view(s, std::strlen(s)));
}
If you have to deal with a pre-C++17 compiler you can check your STL for an implementation defined hash function and call that.
For example, libstdc++ (which is what GCC uses by default) provides std::_Hash_bytes which can be called like this:
#include <functional>
// -> which finally includes /usr/include/c++/$x/bits/hash_bytes.h
#include <cstring>
static size_t hash_cstr_gnu(const char *s)
{
const size_t seed = 0;
return std::_Hash_bytes(s, std::strlen(s), seed);
}
You can use std::collate::hash
e.g. https://www.cplusplus.com/reference/locale/collate/hash/
I am trying to get the address of a static method from a class that is passed as a template argument to another class. Below is a pared down example:
#include <iostream>
#include <array>
using namespace std;
typedef size_t Data;
class MyFunction
{
private:
static const std::array<std::string, 3> values;
public:
template<size_t N>
static void Func(const Data& aData)
{
size_t index = (N > aData ? 2 : (N == aData ? 1 : 0) );
cout << "Function::Func<"<< N << ">:\t" << N << values[index] << aData << endl;
}
typedef decltype(&Func<0>) type;
};
const std::array<std::string, 3> MyFunction::values {"<", "=", ">"};
template<class Function, size_t N>
class FunctionManager
{
private:
static const typename Function::type func_;
static constexpr typename Function::type Create()
{
return &Function::Func<N>; //ERROR: Causes "overloaded function with no contextual information".
}
public:
void operator()(const Data &aData) const
{
func_(aData);
}
};
template<class Function, size_t N>
const typename Function::type FunctionManager<Function, N>::func_ = FunctionManager<Function, N>::Create();
int main()
{
static const size_t N = 6;
auto man = FunctionManager<MyFunction, N>();
man(N/2);
return 0;
}
You can also find the code here. The problem is in the Create() function, I get "address of overloaded function with no contextual type information" error. However, if I change &Function::Func to &MyFunction::Func, it works fine. I would like to make the actual function a template parameter and not hard-code it, anyone have any idea how to fix this problem? Note that I realize there are simpler ways of doing what I'm trying to do, but the actual code instead of a single Function::type creates an array of them using the index trick, etc. Any help would be greatly appreciated.
The error message causes some head scratching, indeed. Here's what's missing:
return &Function::template Func<N>;
// ^^^^^^^^
Function is a template parameter and you need to help the compiler and tell it that the nested name Func names a template.