I'm a little confused as to what is required regarding calling templated functions in C++11, where default values are supplied for the template arguments.
For example, say I have the following templated function
template <class T = double> void foo()
{
/* Do something */
}
and I want to call it somewhere in my code. Are all of these valid calls?
foo(); //Is this OK?
foo<>();
foo<int>();
It compiles fine with GCC 4.7.2, but I'm not sure if it's strictly correct C++. I guess my uncertainty may come from the requirement to use empty angle brackets <> when creating an instance of a templated class using the default template, as described here:
Template default arguments
but I presume in my case having the function brackets () is the critical difference?
A function call to a function template where every template parameter is deducible or has a default can use empty angle brackets or can omit them, both ways are valid.
The difference is that if you omit the angle brackets, you're inviting overload resolution to also consider non-template functions that happen to be named foo and happen to be callable with the same (empty in this case) parameter list.
This hasn't changed in C++11.
Related
I understand that with concepts, a constrained function (regardless how "loose" the constraint actually is) is always a better match than an unconstrained function. But is there any syntax to selectively call the unconstrained version of f() as in the sample code below? If not, would it be a good idea for compilers to warn about uncallable functions?
#include <iostream>
template <typename T> requires(true)
void f() { std::cout << "Constrained\n"; }
template <typename T>
void f() { std::cout << "NOT Constrained\n"; }
int main() {
f<int>();
}
https://godbolt.org/z/n164aTvd3
Different overloads of a function are meant to all do the same thing. They may do it in different ways or on different kinds of objects, but at a conceptual level, all overloads of a function are supposed to do the same thing.
This includes constrained functions. By putting a constrained overload in a function overload set, you are declaring that this is a valid alternative method for doing what that overload set does. As such, if the constraint matches, then that's the function that should be called. Just like for parameters of different types in regular function overloading.
If you want to explicitly call an overload hidden by a constraint, you have already done something wrong in your design. Or more specifically, if some overload is completely hidden by one or more constrained overloads, you clearly have one more overload than you actually needed.
If the constraints match, the caller should be 100% fine with getting the constrained overload. And if this isn't the case, your design has a problem.
So no, there is no mechanism to do this. Just as there's no mechanism to bypass an explicitly specialized template and use the original version if your template arguments match the specialization.
This question already has answers here:
Why not infer template parameter from constructor?
(12 answers)
Closed 7 years ago.
template< class T >
class Foo {
public:
Foo( T t ) { }
};
int main () {
int i = 0;
Foo f( i );
}
In the above code, the compiler complains that template arguments are missing before 'f'. I understand that deducing template arguments for a class from the arguments to the constructor is not part of the standard, but my question is why? Doesn't the compiler have all the information it needs to implicitly instantiate Foo<int> and call its constructor?
Edited to make it clear that I'm calling the constructor with an int (as opposed to a short, long, void*, etc.)
Because nobody has specified how exactly that works. There is a current proposal to the standard committee to make it work. It also lists some of the difficulties:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4471.html
Update: Here's the newest version of the proposal:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0091r0.html
TL;DR: Template specialization
They can, but only template arguments on the function itself, not on the type.
The declaration Foo f(0); is illegal, because there is no type named Foo. Perhaps you were thinking of
auto f = Foo(0);
but that is not allowed either, because the compiler doesn't know what scope to search in (there are infinite potential types with a constructor named Foo and, with specialization, possibly more than one with a constructor Foo(int))
The usual method to do this is with a factory helper function:
auto f = make_foo(0);
where the factory function's return type depends on type deduction of its parameters.
You can imagine that the factory functions could be automatically generated in namespace scope and then the usual function overloading rules applied, but this runs into significant difficulty because there can be template arguments on both the type and the constructor itself. These could simply be concatenated, with the limitation that this would exclude class templates with variadic argument lists, because there would be no way to distinguish where the type parameters end and the function parameters begin.
Foo is a class template, not a class. Its type always needs to be supplied in some way or another for a class to be generated with the correct types. You can't do Foo because Foo isn't a type, but Foo<int> is. It creates a class like this:
class Foo {
public:
Foo( int t ) { }
};
If you only supplied Foo, the compiler wouldn't know how to generate the class. Foo<int> f(0) works because Foo<int> generates the class, substituting T with int. By the type you call the constructor, the compiler already knows that the constructor is accepting an int.
The name of the class you want to instantiate is
Foo<int> (as you indicate).
It is also possible to write Foo<short> f(0), or Foo<unsigned long> f(0),
or Foo<Foo<double>*> f(0). In those cases, however, you don't expect the compiler to be able to guess the type if you write only Foo f(0).
One could imagine that a C++ could have been specified with rules to make
some such guesses in certain ways (such as, the literal 0 implies type parameter int and no other), but then the language would be even more
complicated than it is now and there would be additional ways for
people to make programming errors.
Actually writing what you mean in a declaration like this
seems like not too much to ask.
Edit: After posting this, I noticed in another answer that there is
a proposal to make such a feature of C++, indeed as one could imagine.
This question already has answers here:
Why not infer template parameter from constructor?
(12 answers)
Closed 7 years ago.
template< class T >
class Foo {
public:
Foo( T t ) { }
};
int main () {
int i = 0;
Foo f( i );
}
In the above code, the compiler complains that template arguments are missing before 'f'. I understand that deducing template arguments for a class from the arguments to the constructor is not part of the standard, but my question is why? Doesn't the compiler have all the information it needs to implicitly instantiate Foo<int> and call its constructor?
Edited to make it clear that I'm calling the constructor with an int (as opposed to a short, long, void*, etc.)
Because nobody has specified how exactly that works. There is a current proposal to the standard committee to make it work. It also lists some of the difficulties:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4471.html
Update: Here's the newest version of the proposal:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0091r0.html
TL;DR: Template specialization
They can, but only template arguments on the function itself, not on the type.
The declaration Foo f(0); is illegal, because there is no type named Foo. Perhaps you were thinking of
auto f = Foo(0);
but that is not allowed either, because the compiler doesn't know what scope to search in (there are infinite potential types with a constructor named Foo and, with specialization, possibly more than one with a constructor Foo(int))
The usual method to do this is with a factory helper function:
auto f = make_foo(0);
where the factory function's return type depends on type deduction of its parameters.
You can imagine that the factory functions could be automatically generated in namespace scope and then the usual function overloading rules applied, but this runs into significant difficulty because there can be template arguments on both the type and the constructor itself. These could simply be concatenated, with the limitation that this would exclude class templates with variadic argument lists, because there would be no way to distinguish where the type parameters end and the function parameters begin.
Foo is a class template, not a class. Its type always needs to be supplied in some way or another for a class to be generated with the correct types. You can't do Foo because Foo isn't a type, but Foo<int> is. It creates a class like this:
class Foo {
public:
Foo( int t ) { }
};
If you only supplied Foo, the compiler wouldn't know how to generate the class. Foo<int> f(0) works because Foo<int> generates the class, substituting T with int. By the type you call the constructor, the compiler already knows that the constructor is accepting an int.
The name of the class you want to instantiate is
Foo<int> (as you indicate).
It is also possible to write Foo<short> f(0), or Foo<unsigned long> f(0),
or Foo<Foo<double>*> f(0). In those cases, however, you don't expect the compiler to be able to guess the type if you write only Foo f(0).
One could imagine that a C++ could have been specified with rules to make
some such guesses in certain ways (such as, the literal 0 implies type parameter int and no other), but then the language would be even more
complicated than it is now and there would be additional ways for
people to make programming errors.
Actually writing what you mean in a declaration like this
seems like not too much to ask.
Edit: After posting this, I noticed in another answer that there is
a proposal to make such a feature of C++, indeed as one could imagine.
I am newbie to c++ template. If I defined a template method, which I found I can call non template method
for example
void non_template(double x)
{
}
template<typename T>
void testClass<T>::method1() {
/*****/
T var1;
//call a nontemplate here using var1
non_template(var1);
}
I am not sure why this can be allowed without any compilation errors; If my var1 is int, will it be wrong?
I am not sure why this can be allowed without any compilation errors; If my var1 is int, will it be wrong?
Template classes and functions work slightly differently from non-templated ones: checking for validity is done in 2 passes - once at definition time, the other at instantiation (when the method is first called) time.
When processing the template function, it checks things like syntax, and type not dependent on the template arguments. If these succeed, it will not complain and store the definition of the template in it's state.
When you try to call (instantiate) the template with a particular set of arguments, it will go back to the definition stored and recheck thing that are dependent on the type of parameters passed in.
So, if I try to call your function with an int, double and a float like:
test_calls.method(5.0); // Works as expected
test_calls.method(5); // Works, because int can be converted to double implicitly.
test_calls.method("Hello"); // Doesn't work, because "non-templated" cannot be call with a char const* argument.
The compiler looks for matches by applying permitted conversions to parameters in order to find a match (i.e. a function that can be called). That is true for all functions, not just templates.
If T is a type that can be implicitly converted to a double, then it will be so the "non template" function can be called.
If T cannot be implicitly converted to double, then the compiler will report it cannot find a match in some way.
I find something annoying in C++ and I don't know if there is a trick to avoid this with no overhead. The problem is the following :
For a template function, we can have :
// Function declaration/definition
template<bool Option = false> void myFunction()
{
std::cout<<"Option = "<<Option<<std::endl;
}
// Then I can use :
myFunction<false>();
myFunction<true>();
myFunction(); // <- NO PROBLEM HERE
Now for a template class :
// Class definition/declaration
template<bool Option = false> class MyClass
{
};
// Then I can use :
myClass<false> x;
myClass<true> y;
myClass z; // <- PROBLEM HERE : only "MyClass<> z;" will compile !
Why is the reason of this behaviour ?
Is there any trick to avoid that ?
For a class with optionnal parameters passed as template, I find this not convenient for the end user : he should be able to use the default implementation as a no-templated class...
Why is the reason of this behaviour ?
It's because functions can be overloaded, and types can't.
When you write a function call, the compiler populates an overload set of all the functions it can find with that name, and then figures out which ones match the argument(s) passed. Now, for this to work cleanly with function templates, it allows the template argument types to be deduced from the parameters. Because type parameter inference is allowed in general, it works for your case even when the parameter is defaulted instead.
Types, however, aren't overloaded. While myFunction<true>() and myFunction<false>() are both related to the extent they'll participate in the same overload set, myClass<true> and myClass<false> are separate and unrelated types. With no equivalent of overloading on type names, there's no motivation to add a special case for implicitly naming a fully-specialized template class. The parameters can never be inferred, so it would amount to special syntax only for the case where they're all defaulted.
Is there any trick to avoid that ?
In general, if you want to get template argument deduction for template classes, you can provide a template function wrapper (this works best with C++11 auto)
template <bool Option=false> class MyClass {};
template <bool Option=false> MyClass<Option> make_my_class() {
return MyClass<Option>();
}
// ...
auto z = make_my_class();
Otherwise, I think using typedef (as per Remy's comment) is the best option.
myClass is a class template, not a class. Only myClass<true>, or myClass<>, is a class.
Similarly, myFunction is a function template, not a function. However, when you're invoking a templated function, the template arguments may be deduced for you, and you don't need to specify template arguments explicitly if they can be deduced. Thus the function call expression myFunction(); is valid, and the first argument is deduced as false. It's just that the deduction happens thanks to the default argument rather than matching against function arguments.