Does anyone know why the compilation note is generated for this code? The error occurs when compiling in typename T::value_type e. I checked and value_type exists in vector header typedef _Tp value_type; Thanks
#include <vector>
using namespace std;
template <class T>
void f(T& c)
{
typename T::value_type e = c[0];
}
int main(int argc, char *argv[])
{
vector<int> v = {0, 1};
f(v);
return 0;
}
Compilation:
clang++ -std=c++11 -pedantic -Wall test181.cc && ./a.out
test181.cc:7:28: warning: unused variable 'e' [-Wunused-variable]
typename T::value_type e = c[0];
^
test181.cc:13:5: note: in instantiation of function template specialization
'f<std::vector<int, std::allocator<int> > >' requested here
f(v);
^
1 warning generated.
It's letting you know that you've written to a variable that never gets read, which is usually a code smell. As mentioned in the comments, this is only a warning, not an error.
The note was really pertaining to a warning of an unused variable. Use the variable to get rid of the warning.
Related
I have a class with a templated member function that takes a callable type as an argument and has a return type deduced from the return type of the supplied function using decltype with the trailing return type syntax. A minimal example is shown below.
#include <iostream>
#include <vector>
class point {
public:
std::vector<double> val;
point(double in) : val({in}) {};
template<typename T> auto eval(const T& in) -> decltype(in(val[0]));
};
template<typename T>
auto point::eval(const T& in) -> decltype(in(val[0])){
return in(val[0]);
}
int main(int argc, char *argv[]){
point pt(2.0);
auto f = [](double x){return x*x;};
std::cout << pt.val[0] << std::endl;
std::cout << pt.eval(f) << std::endl;
}
This code compiles and works as expected in clang++ and g++-5 but chokes with the following error in g++-6.
> g++-6 main.cpp -o test -std=c++11 -Wall main.cpp:13:6: error:
> prototype for 'decltype
> (in(0->((point*)this)->point::val.std::vector<_Tp,
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&)' does not match any in class 'point' auto
> point::eval(const T& in) -> decltype(in(val[0])){
> ^~~~~ main.cpp:9:35: error: candidate is: template<class T> decltype (in(0->((point*)this)->point::val.std::vector<_Tp,
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&)
> template<typename T> auto eval(const T& in) -> decltype(in(val[0]));
> ^~~~ main.cpp:9:35: error: 'decltype (in(0->((point*)this)->point::val.std::vector<_Tp,
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&) [with T = main(int, char**)::<lambda(double)>;
> decltype (in(0->((point*)this)->point::val.std::vector<_Tp,
> _Alloc>::operator[]<double, std::allocator<double> >())) = double]', declared using local type 'const main(int, char**)::<lambda(double)>',
> is used but never defined [-fpermissive] main.cpp:9:35: warning:
> 'decltype (in(0->((point*)this)->point::val.std::vector<_Tp,
> _Alloc>::operator[]<double, std::allocator<double> >())) point::eval(const T&) [with T = main(int, char**)::<lambda(double)>]'
> used but never defined make: *** [all] Error 1
The compiler error does not appear if the implementation is written inline, i.e.
template<typename T> auto eval(const T& in) -> decltype(in(val[0])){
return in(val[0]);
}
Additionally in c++14 using automatic return type deduction by changing the signature to
template<typename T> auto eval(const T& in);
works as expected.
Is this a gcc compiler bug or is clang incorrectly accepting the above code?
What if any is the difference between these function signatures?
Why does inlining the implementation make a difference?
Yeah, likely a gcc bug. A workaround is to do
template<typename T>
std::result_of<T(double)> point::eval(const T& in) {
that is because you are not explicitly instantiating template function definition. As far as I understand, it is not valid c++ code and compilers don't have to accept it. If you want to reproduce this error on other compilers, try moving point class to header file and point::eval definition into .cpp file. So you either have to explicitly instantiate this definition for every type of argument (which is impossible with lambdas), or (as I suggest) don't use out-of-line templates unless urgently required.
Here's a small example which is substantially similar to what I'm trying to do:
#include <boost/variant/variant.hpp>
#include <boost/variant/recursive_wrapper.hpp>
#include <utility>
#include <vector>
struct foo {
const char * str;
};
typedef std::pair<float, float> fpair;
//typedef std::vector<boost::variant<int, fpair, foo, vlist>> vlist;
// ^ No...
//typedef std::vector<boost::variant<int, fpair, foo, boost::recursive_wrapper<vlist>>> vlist;
// ^ No...
//template <typename T = vlist<T> >
//using vlist = std::vector<boost::variant<int, fpair, foo, boost::recursive_wrapper<vlist>>>;
// ^ No...
template <typename T = vlist<T> >
using vlist = std::vector<boost::variant<int, fpair, foo, boost::recursive_wrapper<T>>>;
// Still no?
int main () {
std::cout << "Hello world\n";
}
The error I get with gcc 4.8 is:
test.cpp:12:33: error: expected nested-name-specifier before ‘vlist’
template <typename T = typename vlist<T>>
^
test.cpp:12:33: error: expected ‘>’ before ‘vlist’
The error with clang 3.6 is:
test.cpp:12:24: error: unknown type name 'vlist'
template <typename T = vlist<T>>
^
test.cpp:12:29: error: expected ',' or '>' in template-parameter-list
template <typename T = vlist<T>>
^
test.cpp:12:32: error: expected unqualified-id
template <typename T = vlist<T>>
^
3 errors generated.
(Edit: actually these errors are from slightly different versions of the above code, but they all give quite similar messages)
I looked at these earlier, slightly different questions, I'm still stumped:
How to declare a self referencing template type
How to properly declare a self-referencing template type?
Boost Fusion adapt declaration for a templated self referential structure
Does anyone know a trick for this, or is there some reason I'm not aware of that the compiler inherently isn't able to do this?
I believe you just want boost::make_recursive_variant:
#include <boost/variant/variant.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <utility>
#include <vector>
struct foo {
const char* str;
};
typedef std::pair<float, float> fpair;
typedef boost::make_recursive_variant<
int,
fpair,
foo,
std::vector<boost::recursive_variant_>
>::type vlist;
int main() {
std::vector<vlist> vec;
vec.push_back(4);
vec.push_back(fpair{1.0f, 2.0f});
vlist v2(vec);
}
The code is below. The code does not compile on an online compiler, and I have no idea why. It is short and pretty self-explanatory, please look below for details.
#include <iostream>
#include <cmath>
using namespace std;
int N;
int distance(int a, int b){
if(abs(a-b) > N/2){
return N - abs(a-b);
}
return abs(a-b);
}
bool test(int x, int y){
if(distance(x,y) <=2){
return true;
}
return false;
}
int main()
{
N = 2;
cout << "Hello World" << endl;
cout << test(3,4) << endl;
return 0;
}
Error message below:
In file included from /usr/include/c++/4.8.3/bits/stl_algobase.h:65:0,
from /usr/include/c++/4.8.3/bits/char_traits.h:39,
from /usr/include/c++/4.8.3/ios:40,
from /usr/include/c++/4.8.3/ostream:38,
from /usr/include/c++/4.8.3/iostream:39,
from main.cpp:1:
/usr/include/c++/4.8.3/bits/stl_iterator_base_types.h: In instantiation of 'struct std::iterator_
traits<int>':
/usr/include/c++/4.8.3/bits/stl_iterator_base_funcs.h:114:5: required by substitution of 'templ
ate<class _InputIterator> typename std::iterator_traits<_Iterator>::difference_type std::distance
(_InputIterator, _InputIterator) [with _InputIterator = int]'
main.cpp:15:20: required from here
/usr/include/c++/4.8.3/bits/stl_iterator_base_types.h:165:53: error: 'int' is not a class, struct
, or union type
typedef typename _Iterator::iterator_category iterator_category;
^
/usr/include/c++/4.8.3/bits/stl_iterator_base_types.h:166:53: error: 'int' is not a class, struct
, or union type
typedef typename _Iterator::value_type value_type;
^
/usr/include/c++/4.8.3/bits/stl_iterator_base_types.h:167:53: error: 'int' is not a class, struct
, or union type
typedef typename _Iterator::difference_type difference_type;
^
/usr/include/c++/4.8.3/bits/stl_iterator_base_types.h:168:53: error: 'int' is not a class, struct
, or union type
typedef typename _Iterator::pointer pointer;
^
/usr/include/c++/4.8.3/bits/stl_iterator_base_types.h:169:53: error: 'int' is not a class, struct
, or union type
typedef typename _Iterator::reference reference;
using namespace std;
This is a bad idea; it dumps anything that's been declared in the std namespace into the global namespace, where it might conflict with anything you declare in the global namespace.
int distance(int a, int b)
This declares a function in the global namespace that conflicts with a function template of the same name in the std namespace.
if(distance(x,y) <=2)
The std::distance template is a better match than your function, according to the arcane rules of overload resolution. Trying to instantiate that, it fails since it can only be instantiated for iterator types, not int.
The best option is to remove the rogue using-directive, and add std:: to anything you use from the standard library. If you don't want to do that for some reason, then qualify your function call to specify the one declared in the global namespace:
if(::distance(x,y) <=2)
I have the following template function:
template <std::size_t first, std::size_t last, typename T>
bool in_range(T& in)
{
for(auto i = in.begin(); i!=in.end(); ++i)
if(*i<first || *i>last)
return false;
return true;
}
but when I try to use it as such:
std::vector<int> test;
test.push_back(1);
test.push_back(5);
test.push_back(6);
std::cout<<in_range<4,7>(test);
I get this weird error:
main.cpp: In instantiation of 'bool in_range(T&) [with long long unsigned int first = 4ull; long long unsigned int last = 7ull; T = std::vector<int>]':
main.cpp:31:34: required from here
What am I doing wrong?
EDIT: full build log: http://pastebin.com/Cwemq2Hk
If I build that with C++11 support enabled, then it compiles. Here is a demonstation.
Before C++11, auto had a different meaning, and so auto i = ... was invalid - it declared a variable with no type.
I guess you're using GCC; depending on the version, you'll need to specify either -std=c++0x or -std=c++11 as a command-line option.
I have written the following template function for summing the contents of a std::vector object. It is in a file by itself called sum.cpp.
#include <vector>
template<typename T>
T sum(const std::vector<T>* objs) {
T total;
std::vector<T>::size_type i;
for(i = 0; i < objs->size(); i++) {
total += (*objs)[i];
}
return total;
}
When I try to compile this function, G++ spits out the following error:
sum.cpp: In function ‘T sum(const std::vector<T, std::allocator<_Tp1> >*)’:
sum.cpp:6: error: expected ‘;’ before ‘i’
sum.cpp:7: error: ‘i’ was not declared in this scope
As far as I can tell the reason that this error is returned is because std::vector<T>::size_type cannot be resolved to a type. Is my only option here to fall back to std::size_t (which if I understand correctly is often but not always the same as std::vector<T>::size_type), or is there a workaround?
typename std::vector<T>::size_type i;
http://womble.decadent.org.uk/c++/template-faq.html#disambiguation
size_type is a dependent name, you need to prefix it with typename, i.e.:
typename std::vector<T>::size_type i;