I have the following (partial) code in a class where I try to evaluate a value against a list of values via metaprogramming in C++11.
bool eval(GLenum value)
{
return false;
};
template<GLenum One, GLenum... Others>
bool eval(GLenum value)
{
if( value == One )
return true;
// Try out the rest
return eval<Others...>(value);
};
gcc complains:
../emul/GLPart.h: In member function ‘bool
GLPart::eval(GLenum) [with unsigned int One = 519u,
unsigned int ...Others = {}, unsigned int ...ValidEnums = {512u, 513u,
514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’:
../emul/GLPart.h:26:31: instantiated from ‘bool
GLPart::eval(GLenum) [with unsigned int One = 518u,
unsigned int ...Others = {519u}, unsigned int ...ValidEnums = {512u,
513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’
../emul/GLPart.h:26:31: instantiated from ‘bool
GLPart::eval(GLenum) [with unsigned int One = 517u,
unsigned int ...Others = {518u, 519u}, unsigned int ...ValidEnums =
{512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned
int]’ ../emul/GLPart.h:26:31: instantiated from ‘bool
GLPart::eval(GLenum) [with unsigned int One = 516u,
unsigned int ...Others = {517u, 518u, 519u}, unsigned int
...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u},
GLenum = unsigned int]’ ../emul/GLPart.h:26:31: instantiated from
‘bool GLPart::eval(GLenum) [with unsigned int One = 515u,
unsigned int ...Others = {516u, 517u, 518u, 519u}, unsigned int
...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u},
GLenum = unsigned int]’ ../emul/GLPart.h:26:31: instantiated from
‘bool GLPart::eval(GLenum) [with unsigned int One = 514u,
unsigned int ...Others = {515u, 516u, 517u, 518u, 519u}, unsigned int
...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u},
GLenum = unsigned int]’ ../emul/GLPart.h:26:31: instantiated from
‘bool GLPart::eval(GLenum) [with unsigned int One = 513u,
unsigned int ...Others = {514u, 515u, 516u, 517u, 518u, 519u},
unsigned int ...ValidEnums = {512u, 513u, 514u, 515u, 516u, 517u,
518u, 519u}, GLenum = unsigned int]’ ../emul/GLPart.h:26:31:
instantiated from ‘bool GLPart::eval(GLenum) [with
unsigned int One = 512u, unsigned int ...Others = {513u, 514u, 515u,
516u, 517u, 518u, 519u}, unsigned int ...ValidEnums = {512u, 513u,
514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned int]’
../emul/GLPart.h:31:43: instantiated from ‘bool
GLPart::Evaluate(GLenum) [with unsigned int ...ValidEnums
= {512u, 513u, 514u, 515u, 516u, 517u, 518u, 519u}, GLenum = unsigned
int]’ alpha.cpp:8:7: instantiated from here ../emul/GLPart.h:26:31:
error: no matching function for call to ‘GLPart<512u, 513u, 514u,
515u, 516u, 517u, 518u, 519u>::eval(GLenum&)’
So it seems like it chokes on the last recursion when One has a value and Others don't. In this case the template parameters should then be empty. Do I need to declare the ordinary eval in another way? Haven't coded C++ in a while so it may be trivial but I just don't get it ;)
When trying to add template<> to the first eval it chokes:
../emul/GLPart.h:14:11: error: explicit specialization in
non-namespace scope ‘class GLPart’ ../emul/GLPart.h:21:7:
error: too many template-parameter-lists ../emul/GLPart.h: In member
function ‘bool GLPart::Evaluate(GLenum)’:
../emul/GLPart.h:32:23: error: parameter packs not expanded with
‘...’: ../emul/GLPart.h:32:23: note: ‘ValidEnums’
../emul/GLPart.h:32:33: error: expected ‘,’ or ‘;’ before ‘...’ token
Solution:
template<GLenum One>
bool eval(GLenum value)
{
return value == One;
};
template<GLenum One, GLenum Two, GLenum... Others>
bool eval(GLenum value)
{
if( eval<One>(value) )
return true;
// Try out the rest
return eval<Two, Others...>(value);
};
As Bo Persson said, said, the first one is not a template, so calling eval will never call the first version. You want:
template<> //this tells compiler that eval is a template function
bool eval(GLenum value)
{
return false;
};
template<GLenum One, GLenum... Others>
bool eval(GLenum value)
{
if( value == One )
return true;
// Try out the rest
return eval<Others...>(value);
};
Since this tends to produce lots of ambiguity errors, the variation that seems to work unambigously looks like this:
template<GLenum One>
bool eval(GLenum value)
{
return value == One;
};
template<GLenum One, GLenum Two, GLenum... Others>
bool eval(GLenum value)
{
if( value == One )
return true;
// Try out the rest
return eval<Two, Others...>(value);
};
The first overload takes exactly one argument, the second at least two. Taking zero arguments probably doesn't make sense anyway.
Related
I tried to write a very simple variant and visitor implementation as below but I got compile errors that I could not figure out why.
#include <variant>
#include <string>
#include <iostream>
struct foo
{
std::string s;
};
struct bar
{
double s;
};
using var = std::variant<foo, bar>;
struct visitor
{
template <class T>
auto operator()(const T v) -> decltype(v.s)
{
return v.s;
}
};
int main()
{
foo f;
f.s = 3.0;
var x = f;
auto xs = std::visit(visitor{}, x);
std::cout<<xs<<std::endl;
}
The error is so long and is complicate enough to confuse me as a newbie to c++11+
In file included from main.cpp:1:
/usr/local/include/c++/8.1.0/variant: In instantiation of 'static constexpr auto std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...)>, std::tuple<_Rest ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply() [with _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {1}]':
/usr/local/include/c++/8.1.0/variant:825:61: required from 'static constexpr void std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply_single_alt(_Tp&) [with long unsigned int __index = 1; _Tp = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&)> _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; long unsigned int ...__dimensions = {2}; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {}]'
/usr/local/include/c++/8.1.0/variant:813:39: required from 'static constexpr void std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply_all_alts(std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type&, std::index_sequence<__indices ...>) [with long unsigned int ...__var_indices = {0, 1}; _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; long unsigned int ...__dimensions = {2}; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {}; std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2> std::index_sequence<__indices ...> = std::integer_sequence<long unsigned int, 0, 1>]'
/usr/local/include/c++/8.1.0/variant:803:19: required from 'static constexpr std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_S_apply() [with _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; long unsigned int ...__dimensions = {2}; _Variants = {std::variant<foo, bar>&}; long unsigned int ...__indices = {}; std::__detail::__variant::__gen_vtable_impl<std::__detail::__variant::_Multi_array<_Result_type (*)(_Visitor, _Variants ...), __dimensions ...>, std::tuple<_Variants ...>, std::integer_sequence<long unsigned int, __indices ...> >::_Array_type = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2>]'
/usr/local/include/c++/8.1.0/variant:863:38: required from 'static constexpr std::__detail::__variant::__gen_vtable<_Result_type, _Visitor, _Variants>::_Array_type std::__detail::__variant::__gen_vtable<_Result_type, _Visitor, _Variants>::_S_apply() [with _Result_type = std::__cxx11::basic_string<char> _Visitor = visitor&&; _Variants = {std::variant<foo, bar>&}; std::__detail::__variant::__gen_vtable<_Result_type, _Visitor, _Variants>::_Array_type = std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2>]'
/usr/local/include/c++/8.1.0/variant:866:49: required from 'constexpr const std::__detail::__variant::_Multi_array<std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&), 2> std::__detail::__variant::__gen_vtable<std::__cxx11::basic_string<char>, visitor&&, std::variant<foo, bar>&>::_S_vtable'
/usr/local/include/c++/8.1.0/variant:866:29: required from 'struct std::__detail::__variant::__gen_vtable<std::__cxx11::basic_string<char>, visitor&&, std::variant<foo, bar>&>'
/usr/local/include/c++/8.1.0/variant:1394:23: required from 'constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = visitor; _Variants = {std::variant<foo, bar>&}]'
main.cpp:34:38: required from here
/usr/local/include/c++/8.1.0/variant:848:43: error: invalid conversion from 'std::__success_type<double>::type (*)(visitor&&, std::variant<foo, bar>&)' {aka 'double (*)(visitor&&, std::variant<foo, bar>&)'} to 'std::__cxx11::basic_string<char> (*)(visitor&&, std::variant<foo, bar>&)' [-fpermissive]
{ return _Array_type{&__visit_invoke}; }
std::visit requires the return type be same type and value category for all combination:
The return type is deduced from the returned expression as if by decltype. The call is ill-formed if the invocation above is not a valid expression of the same type and value category, for all combinations of alternative types of all variants.
see C++ draft standard [variant.visit]p2:
Requires: For each valid pack m, e(m) shall be a valid expression.
All such expressions shall be of the same type and value category; otherwise, the program is ill-formed.
If for example each struct had an int member x and you return that instead it would not longer be ill-formed see it live on godbolt. In your case you could change the visitor to simply print instead of return the value see it live:
struct visitor
{
template <class T>
void operator()(const T v)
{
std::cout<< v.s;
}
};
I don't know this question is clear or not.
I want make a simple matrix like that
template<typename T>
class Matrix {
private:
T* m_buffer;
int m_row;
int m_col;
public:
template<int N, int M>
Matrix(const T (&x)[N][M]);
};
template<typename T>
template<int N, int M>
inline
Matrix<T>::Matrix(const T (&x)[N][M]) : m_row(N), m_col(M) {
m_buffer = new T[N*M];
std::copy(x, x + N*M, m_buffer);
}
int main() {
int a[2][3] = { {1, 2, 3},
{4, 5, 6} };
Matrix<int> x(a); // This not work
return 0;
}
It seem be not working and get some error when compile. I want to ask how to fix this error.
/usr/include/c++/5/bits/stl_algobase.h: In instantiation of ‘static _OI std::__copy_move<false, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) [with _II = const int (*)[3]; _OI = int*]’:
/usr/include/c++/5/bits/stl_algobase.h:400:44: required from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = const int (*)[3]; _OI = int*]’
/usr/include/c++/5/bits/stl_algobase.h:436:45: required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = const int (*)[3]; _OI = int*]’
/usr/include/c++/5/bits/stl_algobase.h:469:8: required from ‘_OI std::copy(_II, _II, _OI) [with _II = const int (*)[3]; _OI = int*]’
../main.cpp:34:13: required from ‘Matrix<T>::Matrix(const T (&)[N][M]) [with int N = 2; int M = 3; T = int]’
subdir.mk:18: recipe for target 'main.o' failed
../main.cpp:40:21: required from here
/usr/include/c++/5/bits/stl_algobase.h:340:18: error: invalid conversion from ‘const int*’ to ‘int’ [-fpermissive]
*__result = *__first;
Thank you for your support.
The issue seems to be the call to std::copy. You are passing a reference as the first parameter to std::copy, which is not correct. You should be passing a pointer.
To pass a pointer, the following could be done:
std::copy(&x[0][0], &x[0][0] + N*M, m_buffer);
In the above, you are passing the address of the first element in the two dimensional array, and since the data in a 2D array is contiguous, the address of one past the last element is merely specifying N*M.
Live Example
It's not quite what you're asking but using non-type template arguments, you can achieve a constructor like
Matrix<T,ROWS,COLS>(const T(& initializer)[ROWS][COLS])
allows
Matrix<int,2,2> a({{2,2},
{2,2}});
which has the added bonus of allowing you to enforce multiplication rules with the compiler
Try something like this:
// TemplateMatrix.hpp
#pragma once
#include <cstdlib>
#include <cstring>
template<class T, int M, int N>
class Matrix
{
private:
T *m_buffer;
public:
Matrix(const T matrix[M][N])
{
m_buffer = new T[M*N];
memcpy(m_buffer, matrix, M*N*sizeof(T));
}
};
Then, in the main function
#include <iostream>
#include <cstdlib>
#include "TemplateMatrix.hpp"
using namespace std;
int main()
{
int a[2][2] = {{1,1}, {2,2}};
Matrix<int, 2, 2> m(a);
}
Example code test.cpp
#include <array>
#include <string>
int main ()
{
// OK
const std::array<int, 2> array_int = {42, 1337};
std::array<float, array_int.size()> array_float_ok;
// Error
const std::array<std::string, 2> array_string = {"foo", "bar"};
std::array<float, array_string.size()> array_float_error;
return 0;
}
Compiling with g++ 4.8.4 (Ubuntu 14.04)
g++ -Wall -std=c++0x test.cpp -o test
Gives the following error message
test.cpp: In function ‘int main()’:
test.cpp:14:39: error: call to non-constexpr function ‘constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::basic_string<char>; long unsigned int _Nm = 2ul; std::array<_Tp, _Nm>::size_type = long unsigned int]’
std::array<float, array_string.size()> array_float_error;
^
In file included from test.cpp:1:0:
/usr/include/c++/4.8/array:162:7: note: ‘constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::basic_string<char>; long unsigned int _Nm = 2ul; std::array<_Tp, _Nm>::size_type = long unsigned int]’ is not usable as a constexpr function because:
size() const noexcept { return _Nm; }
^
/usr/include/c++/4.8/array:162:7: error: enclosing class of constexpr non-static member function ‘constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::basic_string<char>; long unsigned int _Nm = 2ul; std::array<_Tp, _Nm>::size_type = long unsigned int]’ is not a literal type
/usr/include/c++/4.8/array:81:12: note: ‘std::array<std::basic_string<char>, 2ul>’ is not literal because:
struct array
^
/usr/include/c++/4.8/array:81:12: note: ‘std::array<std::basic_string<char>, 2ul>’ has a non-trivial destructor
test.cpp:14:39: error: call to non-constexpr function ‘constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::basic_string<char>; long unsigned int _Nm = 2ul; std::array<_Tp, _Nm>::size_type = long unsigned int]’
std::array<float, array_string.size()> array_float_error;
^
test.cpp:14:40: note: in template argument for type ‘long unsigned int’
std::array<float, array_string.size()> array_float_error;
^
test.cpp:14:59: error: invalid type in declaration before ‘;’ token
std::array<float, array_string.size()> array_float_error;
^
test.cpp:9:39: warning: unused variable ‘array_float_ok’ [-Wunused-variable]
std::array<float, array_int.size()> array_float_ok;
^
test.cpp:14:42: warning: unused variable ‘array_float_error’ [-Wunused-variable]
std::array<float, array_string.size()> array_float_error;
^
Can someone explain this error? Why does the first example work while the second one does not compile?
The type std::string is not a literal type meaning that it cannot be manipulated as part of a constexpr function at compile time. At compile time, the compiler attempts to evaluate the array_string's size() function. The functions first type parameter as you can see in the first error is set to std::basic_string < char > (aka std::string); therefore, since std::string is not a literal type, the function cannot be evaluated as a constexpr function at compile time and you have an error.
I would refer you to the following to learn more about constexpr.
http://en.cppreference.com/w/cpp/language/constexpr
I would refer you to the following to learn about literal types.
http://en.cppreference.com/w/cpp/concept/LiteralType
Finally, try the following simple code and you will see that int and float are literal types and std::string is not. You can try it out with other types to see what are or aren't literal types.
#include <iostream>
int main(int argc, char** argv)
{
std::cout << std::is_literal_type<int>::value << std::endl;
std::cout << std::is_literal_type<float>::value << std::endl;
std::cout << std::is_literal_type<std::string>::value << std::endl;
return 0;
}
Hope that helps.
John
I got big problems about the compile when I want to use thrust and c++ meanwhile.
Here is the project structure(just a test project):
sortbase.h
#include<iostream>
#include <thrust/device_vector.h>
using namespace std;
template<class T>
class SortBase
{
public:
void Init()
{
}
void resize(const int &x)
{
CV.resize(x);
cout<<"resize succeed!"<<endl;
}
private:
thrust::device_vector<T> CV;
};
sorter.h
#ifndef __SORTER_H__
#define __SORTER_H__
#include <iostream>
#include <thrust/device_vector.h>
#include "sortbase.h"
using namespace std;
template<class T>
void ttest()
{cout<<"tttttttttttttttt";cout<<endl;}
template<class KEY>
class Sorter
{
public:
Sorter():CV(NULL)
{
CV=new SortBase<KEY>();
}
~Sorter()
{
if (CV!=NULL)
{
delete CV;
CV=NULL;
}
}
__host__ __device__
virtual bool operator()(const KEY& x,const KEY& y)const
{
return (x<y);
}
void test()
{
//ttest<KEY>();
resize(5);
}
private:
void resize(const int &x)
{
CV->resize(x);
cout<<"resize: "<<x<<endl;
}
private:
SortBase<KEY> *CV;
};
#endif
main.cpp
#include <iostream>
#include "include/sorter.cu"
using namespace std;
int main(int argc,char **argv)
{
Sorter<int> *sorter=new Sorter<int>();
sorter->test();
return 0;
}
What I do like this:
nvcc -c sorter.cu
g++ -c main.cpp -I/usr/local/cuda/include
g++ sorter.o main.o -o sorter
but the second step gives the error message, a lot of warning and error message.
who can help me?
some warning and error message like these:
/usr/local/cuda/include/thrust/detail/device/cuda/for_each.inl: In function \u2018RandomAccessIterator thrust::detail::device::cuda::for_each_n(RandomAccessIterator, Size, UnaryFunction) [with RandomAccessIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, UnaryFunction = thrust::detail::generate_functor<thrust::detail::fill_functor<int> >]\u2019:
/usr/local/cuda/include/thrust/detail/device/dispatch/for_each.h:56: instantiated from \u2018RandomAccessIterator thrust::detail::device::dispatch::for_each_n(RandomAccessIterator, Size, UnaryFunction, thrust::detail::cuda_device_space_tag) [with RandomAccessIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, UnaryFunction = thrust::detail::generate_functor<thrust::detail::fill_functor<int> >]\u2019
/usr/local/cuda/include/thrust/detail/device/for_each.inl:43: instantiated from \u2018OutputIterator thrust::detail::device::for_each_n(OutputIterator, Size, UnaryFunction) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, UnaryFunction = thrust::detail::generate_functor<thrust::detail::fill_functor<int> >]\u2019
/usr/local/cuda/include/thrust/detail/dispatch/for_each.h:84: instantiated from \u2018OutputIterator thrust::detail::dispatch::for_each_n(OutputIterator, Size, UnaryFunction, thrust::device_space_tag) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, UnaryFunction = thrust::detail::generate_functor<thrust::detail::fill_functor<int> >]\u2019
/usr/local/cuda/include/thrust/detail/for_each.inl:41: instantiated from \u2018OutputIterator thrust::detail::for_each_n(OutputIterator, Size, UnaryFunction) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, UnaryFunction = thrust::detail::generate_functor<thrust::detail::fill_functor<int> >]\u2019
/usr/local/cuda/include/thrust/detail/generate.inl:47: instantiated from \u2018OutputIterator thrust::generate_n(OutputIterator, Size, Generator) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, Generator = thrust::detail::fill_functor<int>]\u2019
/usr/local/cuda/include/thrust/detail/device/cuda/fill.inl:87: instantiated from \u2018OutputIterator thrust::detail::device::cuda::detail::fill_n(OutputIterator, Size, const T&, thrust::detail::false_type) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, T = int]\u2019
/usr/local/cuda/include/thrust/detail/device/cuda/fill.inl:117: instantiated from \u2018OutputIterator thrust::detail::device::cuda::detail::fill_n(OutputIterator, Size, const T&, thrust::detail::true_type) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, T = int]\u2019
/usr/local/cuda/include/thrust/detail/device/cuda/fill.inl:138: instantiated from \u2018OutputIterator thrust::detail::device::cuda::fill_n(OutputIterator, Size, const T&) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, T = int]\u2019
/usr/local/cuda/include/thrust/detail/device/dispatch/fill.h:57: instantiated from \u2018OutputIterator thrust::detail::device::dispatch::fill_n(OutputIterator, Size, const T&, thrust::detail::cuda_device_space_tag) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, T = int]\u2019
/usr/local/cuda/include/thrust/detail/device/fill.inl:47: instantiated from \u2018OutputIterator thrust::detail::device::fill_n(OutputIterator, Size, const T&) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, T = int]\u2019
/usr/local/cuda/include/thrust/detail/dispatch/fill.h:76: instantiated from \u2018OutputIterator thrust::detail::dispatch::fill_n(OutputIterator, Size, const T&, thrust::device_space_tag) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, T = int]\u2019
/usr/local/cuda/include/thrust/detail/fill.inl:46: instantiated from \u2018OutputIterator thrust::fill_n(OutputIterator, Size, const T&) [with OutputIterator = thrust::detail::normal_iterator<thrust::device_ptr<int> >, Size = long unsigned int, T = int]\u2019
/usr/local/cuda/include/thrust/detail/vector_base.inl:757: instantiated from \u2018void thrust::detail::vector_base<T, Alloc>::fill_insert(typename thrust::detail::contiguous_storage<T, Alloc>::iterator, typename thrust::detail::contiguous_storage<T, Alloc>::size_type, const T&) [with T = int, Alloc = thrust::device_malloc_allocator<int>]\u2019
/usr/local/cuda/include/thrust/detail/vector_base.inl:561: instantiated from \u2018void thrust::detail::vector_base<T, Alloc>::insert(typename thrust::detail::contiguous_storage<T, Alloc>::iterator, typename thrust::detail::contiguous_storage<T, Alloc>::size_type, const T&) [with T = int, Alloc = thrust::device_malloc_allocator<int>]\u2019
/usr/local/cuda/include/thrust/detail/vector_base.inl:223: instantiated from \u2018void thrust::detail::vector_base<T, Alloc>::resize(typename thrust::detail::contiguous_storage<T, Alloc>::size_type, typename thrust::detail::contiguous_storage<T, Alloc>::value_type) [with T = int, Alloc = thrust::device_malloc_allocator<int>]\u2019
include/sortbase.h:14: instantiated from void SortBase<T>::resize(const int&) [with T = int]
include/sorter.cu:40: instantiated from void Sorter<KEY>::resize(const int&) [with KEY = int]
include/sorter.cu:35: instantiated from void Sorter<KEY>::test() [with KEY = int]
main.cpp:9: instantiated from here
/usr/local/cuda/include/thrust/detail/device/cuda/for_each.inl:93: error: invalid application of sizeof to incomplete type thrust::detail::STATIC_ASSERTION_FAILURE<false>
/usr/local/cuda/include/thrust/detail/device/cuda/arch.h: At global scope:
/usr/local/cuda/include/thrust/detail/device/cuda/arch.h:59: warning: inline function size_t thrust::detail::device::cuda::arch::compute_capability() used but never defined
I think that the problem is you are including your .cu file from a .cpp file. Thrust code can only be used from .cu files, which must be compiled by NVCC, not by the host compiler g++. So you need to move all of your Thrust and CUDA device code inside .cu files in functions that can be called from your .cpp files.
Harrism is right. If you are going to compile a file using gpu, you must use .cu for the file and nvcc like:
nvcc -o test test.cu
I need to insert a 1D array into the hashset.
But I got error while compiling.
#include <stdio.h>
#include <stdlib.h>
#include <hash_set.h>
using namespace std;
int hash_comp(const int* state1,const int* state2) {
int result = 0;
for (i = 0; i < 16; i++)
{
if (state1[i] != state2[i]) {
result = -1;
}
}
return result;
}
struct eqArray
{
bool operator()(const int* a1,const int* a2) const
{
return hash_comp(a1,a2) == 0;
}
};
hash_set<int*,hash<int*>,eqArray> closelist;
int main(int argc, char** argv)
{
const int sn[16] = {1,2,3,4,5,6,0,8,9,10,11,12,13,14,7,15};
closelist.insert(sn);
return 0;
}
/usr/include/c++/4.2.1/ext/hashtable.h: In member function 'size_t __gnu_cxx::hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>::_M_bkt_num_key(const _Key&, size_t) const [with _Val = int*, _Key = int*, _HashFcn = __gnu_cxx::hash<int*>, _ExtractKey = std::_Identity<int*>, _EqualKey = std::equal_to<int*>, _Alloc = std::allocator<int*>]':
/usr/include/c++/4.2.1/ext/hashtable.h:599: instantiated from 'size_t __gnu_cxx::hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>::_M_bkt_num(const _Val&, size_t) const [with _Val = int*, _Key = int*, _HashFcn = __gnu_cxx::hash<int*>, _ExtractKey = std::_Identity<int*>, _EqualKey = std::equal_to<int*>, _Alloc = std::allocator<int*>]'
/usr/include/c++/4.2.1/ext/hashtable.h:1006: instantiated from 'void __gnu_cxx::hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>::resize(size_t) [with _Val = int*, _Key = int*, _HashFcn = __gnu_cxx::hash<int*>, _ExtractKey = std::_Identity<int*>, _EqualKey = std::equal_to<int*>, _Alloc = std::allocator<int*>]'
/usr/include/c++/4.2.1/ext/hashtable.h:437: instantiated from 'std::pair<__gnu_cxx::_Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>, bool> __gnu_cxx::hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>::insert_unique(const _Val&) [with _Val = int*, _Key = int*, _HashFcn = __gnu_cxx::hash<int*>, _ExtractKey = std::_Identity<int*>, _EqualKey = std::equal_to<int*>, _Alloc = std::allocator<int*>]'
/usr/include/c++/4.2.1/ext/hash_set:197: instantiated from 'std::pair<typename __gnu_cxx::hashtable<_Value, _Value, _HashFcn, std::_Identity<_Tp>, _EqualKey, _Alloc>::const_iterator, bool> __gnu_cxx::hash_set<_Value, _HashFcn, _EqualKey, _Alloc>::insert(const typename __gnu_cxx::hashtable<_Value, _Value, _HashFcn, std::_Identity<_Tp>, _EqualKey, _Alloc>::value_type&) [with _Value = int*, _HashFcn = __gnu_cxx::hash<int*>, _EqualKey = std::equal_to<int*>, _Alloc = std::allocator<int*>]'
src/ods2.cpp:677: instantiated from here
If you use a std::array<int, 16> instead of int*, all your problems will go away. If you have no C++11 compiler, you can use boost::array instead. Also, replace hash_set with unordered_set.
It appears there is no specialization of std::hash for std::arrays, so I wrote my own:
#include <unordered_set>
#include <array>
namespace std
{
template<typename T, size_t N>
struct hash<array<T, N> >
{
typedef array<T, N> argument_type;
typedef size_t result_type;
result_type operator()(const argument_type& a) const
{
hash<T> hasher;
result_type h = 0;
for (result_type i = 0; i < N; ++i)
{
h = h * 31 + hasher(a[i]);
}
return h;
}
};
}
std::unordered_set<std::array<int, 16> > closelist;
int main()
{
std::array<int, 16> sn = {1,2,3,4,5,6,0,8,9,10,11,12,13,14,7,15};
closelist.insert(sn);
}
You didn’t post the actual error message, only the trace. That said, it’s probably because your set uses non-const int* while your data is const.
That said, I’d suggest using unordered_set instead of hash_set(either from std::tr1 if your compiler supports that, or from std if your compiler supports C++11 or from Boost), and heed Fred’s advice of using an {std,boost}::array instead of a raw pointer.
I don't think that there exists a specialized hash<int*>. I added this:
namespace __gnu_cxx{ //I'm not sure what compiler version you used,
//mine wanted this
template<>
struct hash<const int*>{
size_t operator()(const int*a) const{
size_t r = 0;
for (int i=0;i<16;i++)
r = (r<<1) ^ a[i]; //not sure if it makes sense as a hash.
return r;
}
};
}
I also put in some consts and it compiles.