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);
Related
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 last month.
Improve this question
Consider a BasicCharp class with two constructors:
template <class CharType>
class BasicCharp {
public:
using value_type = CharType;
using pointer = value_type*;
public:
//1
template<size_t SIZE>
constexpr BasicCharp(value_type (&str)[SIZE]) noexcept
: m_Length(SIZE)
, m_String(str) {}
//2
constexpr BasicCharp(pointer string) noexcept
: m_Length(countElems(string))
, m_String(string) {}
private:
size_t m_Length;
pointer m_String;
};
Constructing:
BasicCharp<const char> str = "test";
This calls constructor 2, however if there is no constructor 2, this does call constructor 1.
How to keep constructor 2, but enforce using constructor 1 if possible?
A c++17 solution is preferred, but any standart is welcome.
The goal is to deduce string literal's size at compile time, but if a pointer is passed, size should be calculated by the constructor.
Your overloads are ambiguous; a decayed array pointer is no better or worse candidate than a non-decayed one. It only compiles because non-template overloads are a better match than template ones.
What you can do is make the pointer overload a worse overload candidate, e.g. by introducing a user-defined conversion sequence.
struct ptr { pointer p; ptr(pointer p) : p(p) {} };
constexpr BasicCharp(ptr string) noexcept
: m_Length(countElems(string.p))
, m_String(string.p) {}
Not exactly the same, but you might tag dispatch, something like:
template <typename > struct Tag{};
template <class CharType>
class BasicCharp {
// ...
public:
template<typename T>
constexpr BasicCharp(const T& str) noexcept : BasicCharp(str, Tag<T>{})
{
// Or alternatively, use if constexpr here
}
private:
template<std::size_t SIZE>
constexpr BasicCharp(const value_type (&str)[SIZE],
Tag<value_type[SIZE]>) noexcept
: m_Length(SIZE)
, m_String(str) {}
constexpr BasicCharp(const value_type*string, Tag<const value_type*>) noexcept
: m_Length(countElems(string))
, m_String(string) {}
};
You can assign the result to constexpr variable, but it is not 100% garanted that this will be done compile time, also you can use consteval, in this case if variable isn't assigned compile time you will get error(consteval works from c++20)
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";
}
This question already has answers here:
How to ensure constexpr function never called at runtime?
(5 answers)
Closed 6 years ago.
Given the following code:
constexpr int omg() { return 42; }
const int a = omg(); // NOT guaranteed to be evaluated at compile time
constexpr const int a = omg(); // guaranteed to be evaluated at compile time
Is there a way to force something to be evaluated at compile time without assigning it to something constexpr (or in a compile time context like a template parameter ot enum shenanigans)?
Something like this:
const int a = force_compute_at_compile_time(omg());
perhaps something like this (which doesn't compile - I'm not much into constexpr yet):
template<typename T> constexpr T force_compute_at_compile_time(constexpr const T& a) { return a; }
You could use non-type template arguments:
template <int N> constexpr int force_compute_at_compile_time();
const int a = force_compute_at_compile_time<omg()>();
Since N is a template argument, it has to be a constant expression.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
template <typename Function>
struct function_traits
: public function_traits<decltype(&Function::operator())> {
}; //1 why function_traints inherit from itself?
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
typedef ReturnType (*pointer)(Args...);
typedef std::function<ReturnType(Args...)> function;
}; //2 this class do nothing just typedef type ?
template <typename Function>
typename function_traits<Function>::function
to_function (Function & lambda) {
return static_cast<typename function_traits<Function>::function>(lambda);
}
template <typename Lambda>
size_t getAddress(Lambda lambda) {
auto function = new decltype(to_function(lambda))(to_function(lambda));
//3 func is std::function pointer,this conversion is ok?
void * func = static_cast<void *>(function);
return (size_t)func;
}
int f(int, int) { return 1; }
int g(int, int) { return 2; }
std::function<int(int, int)> lambda1 = [](int a, int b)->int
{
return 1;
};
std::function<int(int, int)> lambda2 = [](int a, int b)->int
{
return 1;
};
void test(std::function<int(int, int)> const& arg,const char* info)
{
std::cout << "test function: ";
std::cout << (void*)getAddress(arg) << " " << info << std::endl;
}
int main()
{
test(lambda1,"lambda1");
test(lambda1,"lambda1");
test(lambda2,"lambda2");
test(lambda2,"lambda2");
test(std::function<int(int, int)>(std::plus<int>()),"plus");
test(std::function<int(int, int)>(std::minus<int>()),"minus");
test(std::function<int(int, int)>(f),"f");
test(std::function<int(int, int)>(g),"g");
}
1 why function_traints inherit from itself?
i known this is Curiously recurring template pattern. the function_traints while be compile to two different class.
2 the second class do nothing just typedef type ?
yes, just for convenient
3 func is std::function pointer,this conversion is ok?
[TODO]
4 the main function result is :
test function: 0x7f9440407f50 lambda1
test function: 0x7f9440407f80 lambda1
test function: 0x7f9440407fb0 lambda2
test function: 0x7f9440407fe0 lambda2
test function: 0x7f9440408010 plus
test function: 0x7f9440408040 minus
test function: 0x7f9440408070 f
test function: 0x7f94404080a0 g
these function above is wrong? i can't use it to check whether two function is equal?
[TODO]
Can you explain the code above? Thank you very much!
why function_traints inherit from itself?
It doesn't. Function and decltype(&Function::operator()) are different types, thus function_traits<Function> and `function_traits are also different and unrelated types.
the second class do nothing just typedef type ?
Yes. This is normal for a traits class. In this case, function_traits provides unifirm access to the return type of a callable object, regardless of what this object is: a function pointer, a pointer to member, a lambda or anything else.
func is std::function pointer,this conversion is ok?
No, the conversion is not OK. There are at least three problems with it:
You cannot convert just any lambda to a function pointer, only non-capturing lambdas.
There is a memory leak (the dynamic allocation is totally unnecessary).
A function pointer is in general not compatible with void* and void* is not compatible with size_t. This code may work on some platfirms but not on others.
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);
}