C++ template : no matching function for call - c++

Consider the following code
template <typename T, T one>
T exponentiel(T val, unsigned n) {
T result = one;
unsigned i;
for(i = 0; i < n; ++i)
result = result * val;
return result;
}
int main(void) {
double d = exponentiel<double,1.0>(2.0f,3);
cout << d << endl;
return 0;
}
The compiler tells me this
no matching function for call to 'exponentiel(float, int)'
Why?
What's strange is that exponentiel works with int.

The problem is with the T one and the 1.0 in the template argument list.
You can't have a nontype template parameter of a floating point type and you can't pass a floating point value as a template argument. It's just not allowed (to the best of my knowledge, there's no really good reason why it's not allowed).
g++'s error message here is rather unhelpful. Visual C++ 2010 reports the following on the line where the template is used in main:
error C2993: 'double' : illegal type for non-type template parameter 'one'
Comeau Online reports:
line 13: error: expression must have integral or enum type
double d = exponentiel<double,1.0>(2.0f,3);
^
line 2: error: floating-point template parameter is nonstandard
template <typename T, T one>
^

Related

enable_if compilation question void = nullptr

Does anyone know why assigning type* = 0 doesn't work, while type* = nullptr does? In both cases typedef void type. Thanks
#include <type_traits>
#include <iostream>
template <class T,
typename std::enable_if<std::is_integral<T>::value>::type* = 0>
void do_stuff(T& t) {
std::cout << "do_stuff integral\n";
}
#if 0 // works
template <class T,
typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
void do_stuff(T& t) {
std::cout << "do_stuff integral\n";
}
#endif
struct S {};
int main(int argc, char *argv[])
{
int i = 1;
do_stuff(i);
return 0;
}
Compilation:
clang++ -pedantic -Wall -std=c++11 test190.cc && ./a.out
test190.cc:23:5: error: no matching function for call to 'do_stuff'
do_stuff(i);
^~~~~~~~
test190.cc:6:6: note: candidate template ignored: substitution failure
[with T = int]: null non-type template argument must be cast to template
parameter type 'typename
std::enable_if<std::is_integral<int>::value>::type *' (aka 'void *')
void do_stuff(T& t) {
^
1 error generated.
Technically speaking, this is because a non-type template argument must be a "converted constant expression" of the parameter type. This means that the argument itself must be a constant expression, and its conversion to the required parameter type must use only the conversions specified in [expr.const]/4.
According to [expr.const]/4, null pointer conversions are only allowed from std::nullptr_t. In other words, the conversion from 0 to a null pointer value is not allowed as part of the implicit conversion sequence in a converted constant expression.
Yet it's perfectly legitimate to specify static_cast<T*>(0) as a template argument to a non-type template parameter of type T*. In other words, a null pointer conversion from 0 is allowed as part of a constant expression. It's only when the conversion is done at a certain point---after computing the argument and while converting the argument type to the parameter type---that the standard forbids it.
I have no idea about the rationale for this rule.
** nullptr and 0 are not the same. **
For a very clear explanation please see the following:
https://hackernoon.com/what-exactly-is-nullptr-in-c-94d63y6t
#brian has provided a very good technical answer, but I felt it necessary to add this answer since we should no longer be trying to use 0 for pointer values.

use type_traits to limit type of template member function

I'm writing a template class with a method that performs some bitwise operations, so I want to limit the type in the case this method is used within is_integral. I took the simple example here and modified a bit as follows:
#include <iostream>
#include <type_traits>
template <typename T>
class A
{
public:
A();
T foo(T i) {
static_assert(std::is_integral<T>::value, "Integer required.");
return (i & 2);
}
private:
T x;
};
int main() {
A<double> a;
std::cout << a.foo(3) << std::endl;
return 0;
}
However, compiler gives me 2 compile errors at static_assert():
static_assert failed "Integer required."
and at return (i & 2);:
invalid operands to binary expression ('double' and 'double')
My question is, if it will show the error at line return (i & 2); anyway, using type_traits to check for type here seems useless? And, is there anyway to throw the error to console output when it runs, instead of making it unable to be compiled?
My question is, if it will show the error at line return (i & 2); anyway, using type_traits to check for type here seems useless?
It's true that it's unfortunate that you get subsequent compile errors anyway, but which compile error do you find more readable?
"Integer required."
invalid operands to binary expression (double and double)
I know what I did wrong about the first one - I have A<double> but foo() requires an integer. No idea about the second. Am I misusing your class template or does it have a bug?
And, is there anyway to throw the error to console output when it runs, instead of making it unable to be compiled?
You want it to be a compile error. Catching errors at compile time is a lot better than catching errors at compile time.
Compiler is trying to report as many errors as it can. static_assert reports an error, but there is another error as well (using double argument for &) so it also is reported.
If you want to limit output to one error, you should have two sfinae-enabled overloads and have a second one (for anything but integrals) consist of a single static_assert.
As for your last question, the whole purpose of doing static_assert is to trigger errors at compile time, not runtime.
Here's another way to achieve the same thing. You may or may not prefer the error messages:
#include <iostream>
#include <type_traits>
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
class A
{
public:
A();
T foo(T i) {
return (i & 2);
}
private:
T x;
};
int main() {
A<double> a;
std::cout << a.foo(3) << std::endl;
return 0;
}
sample errors:
In file included from /opt/gcc-5.3.0/include/c++/5.3.0/bits/move.h:57:0,
from /opt/gcc-5.3.0/include/c++/5.3.0/bits/stl_pair.h:59,
from /opt/gcc-5.3.0/include/c++/5.3.0/bits/stl_algobase.h:64,
from /opt/gcc-5.3.0/include/c++/5.3.0/bits/char_traits.h:39,
from /opt/gcc-5.3.0/include/c++/5.3.0/ios:40,
from /opt/gcc-5.3.0/include/c++/5.3.0/ostream:38,
from /opt/gcc-5.3.0/include/c++/5.3.0/iostream:39,
from /tmp/gcc-explorer-compiler11636-75-1ve7gbt/example.cpp:1:
/opt/gcc-5.3.0/include/c++/5.3.0/type_traits: In substitution of 'template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = std::integral_constant<bool, false>::value; _Tp = void]':
19 : required from here
/opt/gcc-5.3.0/include/c++/5.3.0/type_traits:2388:61: error: no type named 'type' in 'struct std::enable_if<false, void>'
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
^
/tmp/gcc-explorer-compiler11636-75-1ve7gbt/example.cpp: In function 'int main()':
19 : error: template argument 2 is invalid
A<double> a;
^
20 : error: request for member 'foo' in 'a', which is of non-class type 'int'
std::cout << a.foo(3) << std::endl;
^
Compilation failed

Error when calling an Integral template member function with g++ and clang++ [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 7 years ago.
I'm currently stuck on a compilation error, which I can't really identify...
Here's a minimal working example:
#include <iostream>
template <typename T, int R>
class a_type
{
public:
template <int N>
double segment()
{
return 42;
}
};
template <int M>
double func()
{
a_type<double, M> a;
return a.segment<1>();
}
int main(int argc, char *argv[])
{
std::cout << func<10>() << std::endl;
return 0;
}
The error message from GCC reads:
g++ main.cpp -o main
main.cpp: In function 'double func()':
main.cpp:18:26: error: expected primary-expression before ')' token
return a.segment<1>();
^
main.cpp: In instantiation of 'double func() [with int M = 10]':
main.cpp:23:28: required from here
main.cpp:18:22: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
return a.segment<1>();
^
Clang also says something similar:
clang++ main.cpp -o main
main.cpp:18:26: error: expected expression
return a.segment<1>();
^
So based on GCC's error message, 'a.segment' is a member function call missing the parentheses, which obviously gets rejected. But that does not make sense at all, since I don't see any reason for treating that expression as such.
Moreover, if I change M to any integral number on line 17, like so:
#include <iostream>
template <typename T, int R>
class a_type
{
public:
template <int N>
double segment()
{
return 42;
}
};
template <int M>
double func()
{
a_type<double, 58> a;
return a.segment<1>();
}
int main(int argc, char *argv[])
{
std::cout << func<10>() << std::endl;
return 0;
}
then the code compiles and produces the expected result.
I would be very happy if somebody could enlighten me and show me what I am missing here.
The compiler doesn't know that a.segment is a template (it might depend on the value of M). So you have to tell it:
return a.template segment<1>();
In your second example it knows everything about the type of a, and so there is no problem.
The compiler tells you that it has problems with
a_type<double, M> a;
return a.segment<1>();
because it cannot tell what members a can have, as it is a template (that might be specialized for some values of M).
main.cpp:18:22: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
return a.segment<1>();
^
If segment is a template, it would be treated as segment<1>. If segment is a member variable of a, it should be compiled as a.segment < 1. How is the compiler to know?
You can fix this by using
return a.template segment<1>();

Clang " couldn't infer template argument " whereas gcc / g++ can. Which is right?

I have been trying to compile a project (which is fine using gcc/g++) with clang and compilation stuck on a template invocation.
I've tried to create the simplest similar piece of code exhibiting the same error message. Here it is:
#include <vector>
#include <utility>
#include <iostream>
using namespace std;
int A( double in )
{
return 1;
}
int A( int in )
{
return 1;
}
template<class M, class T>
M test(T input, M (fun) (T) )
{
return fun( input );
}
int main( int argc, const char *argv[] )
{
cout << test( (int) 1, A ) << test( (double) 1.2, A ) << endl;
return 0;
}
The error from clang (appears twice of course):
error: no matching function for call to 'test'
candidate template ignored: couldn't infer template argument 'M'
Gcc doesn't complain.
Please note M is the return type and is always "int".
Does someone know which is right and why?
Thanks
g++ is wrong. From C++11 [temp.deduct.type]p5:
The non-deduced contexts are: [...]
- A function parameter for which argument deduction cannot be done because the associated function argument is [...] a set of overloaded functions, and [...] more than one function matches the function parameter type
This determination is made without regard to template parameters that might have been deduced elsewhere, so the fact that T must deduce as int is not relevant here. This makes the entire parameter M (fun)(T) a non-deduced context. Therefore M cannot be deduced, just as Clang claims.
g++ appears to incorrectly be using the 'T = int' deduction from the first function parameter when determining whether the second parameter is a non-deduced context. Reversing the order of the function parameters causes g++ to reject the code too:
int A(double);
int A(int);
template<class M, class T>
M test(M (fun) (T), T input) {
return fun( input );
}
int main( int argc, const char *argv[]) {
test(A, 1);
test(A, 1.2);
}
My previous answer (now deleted) was wrong. Clang is wrong.
The compiler should be able to deduce the type M because the function argument is M(fun)(T). Note that there is no M in the function pointer argument list, so this corresponds to the T() (C++11) / T(*)() (C++93) in 14.8.2.5:
where (T) represents a parameter-type-list where at least one parameter type contains a T, and () represents a parameter-type-list where no parameter type contains a T.

How to pass array to function template with reference

I am learning c++ template concepts. I do not understand the following.
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
T fun(T& x)
{
cout <<" X is "<<x;
cout <<"Type id is "<<typeid(x).name()<<endl;
}
int main ( int argc, char ** argv)
{
int a[100];
fun (a);
}
What i am trying?
1) T fun (T & x)
Here x is a reference, and hence will not decayed 'a' into pointer type,
but while compiling , i am getting the following error.
error: no matching function for call to ‘fun(int [100])’
When I try non-reference, it works fine. As I understand it the array is decayed into pointer type.
C-style arrays are very basic constructs which are not assignable, copyable or referenceable in the way built-ins or user defined types are. To achieve the equivalent of passing an array by reference, you need the following syntax:
// non-const version
template <typename T, size_t N>
void fun( T (&x)[N] ) { ... }
// const version
template <typename T, size_t N>
void fun( const T (&x)[N] ) { ... }
Note that here the size of the array is also a template parameter to allow the function to work will all array sizes, since T[M] and T[N] are not the same type for different M, N. Also note that the function returns void. There is no way of returning an array by value, since the array is not copyable, as already mentioned.
The problem is in the return type: you cannot return an array because arrays are non-copiable. And by the way, you are returning nothing!
Try instead:
template <typename T>
void fun(T& x) // <--- note the void
{
cout <<" X is "<<x;
cout <<"Type id is "<<typeid(x).name()<<endl;
}
And it will work as expected.
NOTE: the original full error message (with gcc 4.8) is actually:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:17:10: error: no matching function for call to ‘fun(int [100])’
fun (a);
^
test.cpp:17:10: note: candidate is:
test.cpp:7:3: note: template<class T> T fun(T&)
T fun(T& x)
^
test.cpp:7:3: note: template argument deduction/substitution failed:
test.cpp: In substitution of ‘template<class T> T fun(T&) [with T = int [100]]’:
test.cpp:17:10: required from here
test.cpp:7:3: error: function returning an array
The most relevant line is the last one.