I'm interested to know whether one can distinguish between function calls using arguments provided by compile-time constants and those without?
For example:
int a = 2;
foo( a ) // #1: Compute at run-time
foo( 3 ) // #2: Compute at compile-time
Is there any way to provide overloads that distinguish between these two cases? Or more generally, how do I detect the use of a literal type?
I've looked into constexpr, but a function parameter cannot be constexpr. It would be neat to have the same calling syntax, but be able to generate different code based on the parameters being literal types or not.
You cannot distinguish between a compile-time literal int and a run-time variable int. If you need to do this, you can provide an overload that can only work at compile-time:
void foo(int ); // run-time
template <int I>
void foo(std::integral_constant<int, I> ); // compile-time
I think the above answers somehow miss the point that the question was trying to make.
Is there any way to provide overloads that distinguish between these two cases? Or more generally, how do I detect the use of a literal type?
this is what a 'rvalue reference' is for. literal type is a rvalue.
It would be neat to have the same calling syntax, but be able to generate different code based on the parameters being literal types or not.
you can simply overload your foo() function as:
void foo(int&& a);
So when you call the function with a literal, e.g. foo(3), the compiler knows you need the above overload, as 3 is a rvalue. If you call the function as foo(a), the compiler will pick up your original version foo(const int& a); as int a=2; is a lvalue.
And this gives you the same calling syntax.
In the general case you couldn't get foo(3) evaluated at compile time. What if foo(x) was defined as add x days to the current date - and you first run the program next Tuesday? If it really is a constant then use a symbolic constant. If it is a simple function you could try a define (which will be replaced at compile time with the implementation -but it still will be evaluated at runtime)
e.g.
#define MIN(x,y) ((x)<(y)?(x):(y))
Related
Auto keyword is used to infer the type of the variable based on the initialization. But I read on internet that auto can't determine the type of the function parameters. I didn't understand the reason why auto can't determine the type when used with function parameters. Can any one please let me know why auto can't be used with function parameters and any other cases where auto keyword can't be used to determine the type.
"Can't" is a strong word. After all, lambda parameters can use auto (in C++14). It's not so much "can't" as "doesn't". And perhaps "won't".
The question ultimately comes down to this: what does this actually do?
void foo(auto x)
{
std::cout << x << std::endl;
}
auto deduction is ultimately based on providing an initializing expression, which is used to deduce the actual type. This declaration contains no initializing expression.
C++ is a statically typed language; that means the compiler must be able to determine the type of every expression and object at compile time. From just the above, the compiler can deduce nothing.
So how can the compiler know that std::cout << x is legal C++ syntax? It can only tell that if there is an operator<< overload that takes std::cout and x. It can't figure out what is being called without first knowing the type of x. Which it doesn't; it can be different for different invocations of the function.
However, there is one C++ construct where the above makes sense: a template. This is exactly what using auto in lambda parameters does; it implicitly transforms the function into a template function. So [](auto x) {return x;} effectively becomes an operator something like this:
template<typename T>
auto operator()(T x) {return x;}
However, this conversion doesn't just fall out of having auto as a deduction syntax. It has to be something the standard is explicitly written to require. And, with the exception of C++14 generic lambdas, it doesn't.
Concepts TS includes this facility. However, this is merely an extension of the ability to use concepts in function parameter lists at all. That is, they already have a way to make a function implicitly create a template function, so they just added auto as essentially a case of "a concept that accepts any type".
But this was explicitly excluded from the C++20 version of concepts. The general reason for this exclusion is that, up until this point, template functions could be detected because they always had to have some special syntax. Namely, the inducer template<args>. With the Concepts TS version, there is concern that people will write template functions without realizing it.
And template functions behave differently from non-template functions. A template function is a family of functions, so you can't get a pointer to the family itself. You'd have to explicitly instantiate the template to get a pointer to that particular function.
How can I in C++ make a function accept every Object, so I can give it numbers, String or other Objects. I am not very well in C++, I hope it's not a totally stupid question...
Edit: Ok, an example: if you want to try to wrap the std::cout streams into normal functions, that funtion should be able to accept everything - from Integers over Floats to complex Objects. I hope it's more clear now!
You can overload your function for different types, i.e.
size_t func(int);
size_t func(std::string);
Alternatively and/or additionally, you can provide a function template, which is a way to tell the compiler how to generate your function for any particular type, for example
template<typename T>
size_t func(T const&) { return sizeof(T); }
You may use more advanced techniques such as SFINAE to effectively overload those template functions, i.e. to use different templates for different kind of types T (i.e. integral types, pointer, built-in types, pod, etc). The compiler will then pick the best-fitting func() (if any) for any function call it encounters and, if this is a template, generate an appropriate function.
This requires no re-coding.
A completely different approach is to use a generic erasure type, such as boost::any, when the function will need to resolve the expected types at coding-time (as opposed to compile-time):
size_t func(boost::any const&x)
{
auto i = boost::any_cast<const int*>(x);
if(i) return func(*i);
// etc for other types, but this must be done at coding time!
}
You can use templates for this purpose:
template <typename T>
void foo(T const & value)
{
// value is of some type T, which can be any type at all.
}
What you can actually do with the value may be rather limited without knowing its type -- it depends on the goal of your function. (If someone attempts to call the function with an argument type that causes that function specialization to be ill-formed then your template function will fail to instantiate and it will be a compile-time error.)
I'm not sure what you're trying to accomplish, but you can pass a void pointer as a parameter.
void foo(void* bar);
If I understood you correctly you might wanna try using templates http://en.cppreference.com/w/cpp/language/function_template
You are probably looking for templates.
I suggest you read this.
Is valid to have
int func();
float func(int x);
I know isn't possible overloading without templates by return type only, but this is valid correct?
Yes it is. The rule for overloading is that the parameters need to be of different type and/or number; when this is satisfied, the return type can be different for the various overloads. Given the actual arguments, the compiler can determine which overload to call.
Only overloading by return type is invalid, because the compiler cannot make a choice based on the return value; suppose you have overloads int f() and float f(), and you do
(void)f();
In this situation, there's no telling which f you intended to call. (Unless there would be some arbitrary preference for types specified in the Standard, but there isn't, and it would be hard to come up with a sensible one.)
Functions are identified by their signature.
in C++ function signature include,
name
argument type
no of arguments
order of argument
Return type of function is not consider as a part of signature.
When a function call is encountered in a program then the compiler will look for functions with that name. If multiple functions have same name(function overloading). then the compiler will check the above signature. if an exact match is not found then compiler will do some conversions and check for a match. Still not found a match it will show an error
Yes, it is correct. A function is defined by
the namespace
the name of the function
the types of arguments
But, the return type is not taken into account.
See this example :
int f(); // correct
double f(int x); // correct
void f(double y); // correct, the type is different
char f(int z); // Not correct, same signature than the 2nd function
You already got a few answer stating that it is possible, but a different question is whether it is desirable, and at this point I would advice against it in your case as it puts a burden on the user: they need to figure out what overload is picked to know what the function returns.
Note that this is not a statement that in general it is not desirable, there are many cases where having different return types for different functions make sense, for example sqrt taking a float will return a float, and if the input is a double it will produce a double, but it is natural from the syntax and the call what the return type is.
In the artificial example you provided that is not the case, or at least it is not obvious, so I'd recommend not to overload but produce different named functions.
Yes this is fine as you have different arguments for two overloads.Just for your information why compiler can't deduce from only return types which overload to call.
There's a concept called name mangling. Compiler mangles name of each function as per it's ease to call that appropriately.So if a function is,
int foo (int x );
mangled name would be something in line with foo_int. In this return type is not taken into account. So if I have two overloads like
int foo (int x );
int foo (char x);
mangled names would be something
foo_int
foo_char
respectively. But if you only choose return type for your overload resolution then it will fail as return type is not taken into account in name mangling.
The std::get function uses template parameter as a regular parameter.
As an example:
std::tuple <int, double, long &, const char *> bar(18, 6.5, 12, "Hello!");
cout << std::get<2>(bar); // Print the tuple’s third element.
Why this function designed this way?
Why not using a regular parameter instead?
For example, something like: std::get(bar, 2) or std::get(2, bar)
A function must have a well-defined return type, specified at compile time. Here the template specialisation get<2> is a function returning long&; but your version would have to return a different type depending on its argument, specified at runtime, which is impossible.
Hopefully, this demonstration is explanation enough:
int x;
std::cin >> x;
auto i = std::get(bar, x);
Keeping in mind that in C++ the type of any object must be known at compile time, what type is i? Note that you cannot pass variables as template arguments, you must pass constant expressions, so the above problem doesn't exist when the integer is a template argument.
Perhaps more relevant to your example is this.
std::cout << std::get(bar, x);
Each overload of operator<< is a different function. Which function to call is determined at compile time, based on the arguments. So how can the compiler determine which overload to call in the above statement? What if you had a tuple member which didn't even have an overload?
Consider the following function :
template <typename Type>
void f(const Type& x)
I would like to do something special (without specialization) in it whether the passed type is an empty std::tuple or an empty std::array. For a tuple of nu elements, I can use std::is_same<Type, std::tuple<>>::value but what trick can I use to detect an zero-element array ?
(I am searching for a solution that do not require the creation of another function or class, ...)
You can use std::tuple_size, as it will also work for std::array! See here. Simply use:
std::tuple_size<Type>::value == 0
to check if Type is an empty std::tuple<> or an empty std::array<T,0>.
With the above, the question remains what happens if Type is neither a std::tuple not a std::array. The general approach I see is this:
constexpr bool IsNotTupleOrArray =
!std::is_class<Type>::value ||
std::is_same<Type,ExcludeThisClass>::value ||
sizeof(Type)>1 || // non-portable, works for GCC 4.8+
...;
std::conditional< IsNotTupleOrArray,
std::false_type,
std::tuple_size<Type> >::type::value;
which basically means that you have to explicitly exclude other types. For example is_class<Type> excludes all fundamental types like int, pointers, etc.
If you don't want to do it without specialization, why not doing it with overload? ;) Specializing a function template is sometimes (no, often) a bad idea. With some SFINAE trick it wouldn't be difficult to create an overload that is selected only when those two conditions apply.
However, I already hear you shouting that it's not what you wanted to do: what you wanted is some kind of if inside of f() that would be executed in case the condition is true, and a corresponding else branch that would be executed when the condition is false.
However, notice that this would not be a static if, but a regular run-time if: in other words, the compiler would know at compile-time with 100% certainty that one of those two branches is never going to be executed (and it would probably issue an annoying warning about it), but it will have to parse both branches and prove them legal.
In practice, this means that you won't be able to put statements that depend on the particular type T (or on properties of T) in order to be compilable. For instance, in the code below compile_time_expression determines whether type T has a member function foo() or a member function bar():
T obj;
if (compile_time_expression)
{
obj.foo();
}
else
{
obj.bar();
}
However, the above won't compile if that particular T doesn't have both a member function foo() and a member function bar(): since what you have here is a run-time if, the compiler will have to parse both branches and make sure they're both compilable - and then possibly optimize away the one that is never going to be executed.
Unfortunately, C++ does not have any construct such as static if (yet?), so overloading + SFINAE is the right way to tackle this problem.