I am facing error C2783.
I reproduce error with similar structure test case.
Here is test case:
#include <iostream>
namespace ns1 {
template <class T> class class_1 {};
}
namespace ns2 {
using namespace ns1;
template <typename T> inline ns1::class_1<T> myfunc();
template<typename T>
inline ns1::class_1<T> myfunc() {
int a,b;
std::cin>>a;
std::cin>>b;
if(a<b) return true;
else return false;
}
}
namespace ns3 {
struct myStruct {
ns1::class_1<double> var1;
ns1::class_1<double> var2;
myStruct ( const ns1::class_1<double>& cl0= ns2::myfunc<double>(),
const ns1::class_1<double>& cl1= ns2::myfunc<double>()): var1(cl0), var2(cl1) {};
};
}
Error is :
error C2783: 'ns1::class_1 ns2::myfunc(void)' : could not deduce template argument for 'T'
Also i wonder why its giving error for line 27 (cl0) but not line 28 (for cl1)?
If I try to use this on some function its works fine only giving error when using in structure arguments.
This is a compiler bug. If you replace the contents of myfunc with valid code (as suggested), it still doesn't work. For a description, status (and acknowledgement) of the bug, see Microsoft Connect. You might try to use a helper type to get argument deduction (which works):
namespace ns1 {
template <class T> class class_1 {
public: class_1 (int a, int b){}
};
}
namespace ns2 {
template<class T> struct deduction_helper{};
using namespace ns1;
template <typename T> inline ns1::class_1<T> myfunc(deduction_helper<T>);
template<typename T>
inline ns1::class_1<T> myfunc(deduction_helper<T>) {
int a,b;
std::cin>>a;
std::cin>>b;
ns1::class_1<T> c(a,b); return c;
}
}
namespace ns3 {
struct myStruct {
ns1::class_1<double> var1;
ns1::class_1<double> var2;
myStruct ( const ns1::class_1<double>& cl0= ns2::myfunc(ns2::deduction_helper<double>()),
const ns1::class_1<double>& cl1= ns2::myfunc(ns2::deduction_helper<double>())
): var1(cl0), var2(cl1) {};
};
}
int main()
{
ns3::myStruct x;
}
N.B. as the helper type resides in ns2, you could use ADL instead of qualifying the name myfunc.
Related
Why forward declaration as follows :
template<typename T> struct std::hash;
fails to compile with gcc and clang, but compiles with Visual Studio 2015?
gcc 6.1.0 (using coliru):
main.cpp:11:34: error: invalid use of template-name 'std::hash' without an argument list
template<typename T> struct std::hash;
^~~~
clang 3.8.0 (using coliru):
main.cpp:11:29: error: forward declaration of struct cannot have a nested name specifier
template<typename T> struct std::hash;
^~~~~
it works under VS (http://webcompiler.cloudapp.net/). Which compiler is right?
btw. the same declaration is used in C++ Primer 5th edition. Well - nearly the same it uses class instead of struct: template <class T> class std::hash; which is wrong.
full code:
#include <unordered_map>
/*
// compiles with gcc,clang,VS
namespace std {
template<typename T>
struct hash;
}*/
// Compiles only with VS
template<typename T> struct std::hash;
struct MyData {
MyData() {}
MyData(int d1, int d2) : data1(d1), data2(d2) {}
bool operator==(const MyData& rop) const {
return rop.data1 == data1 && rop.data2 == data2;
}
friend struct std::hash<MyData>;
private:
int data1;
int data2;
};
namespace std {
template<>
struct hash<MyData> {
typedef MyData argument_type;
typedef size_t result_type;
size_t operator()(const argument_type& data) const noexcept;
};
size_t hash<MyData>::operator()(const argument_type& data) const noexcept {
return hash<unsigned>()(data.data1) ^ hash<unsigned>()(data.data2);
}
}
int main() {
std::unordered_map<MyData, std::string> mm;
mm[MyData(1,1)] = "test1";
mm[MyData(2,2)] = "test1";
}
The reason, seems to be largely because a forward declaration has to function much like a regular declaration. i.e. encased in a namespace, not prefixed by one. I guess this would allow the same parser to be used for declarations and forward declarations which makes sense.
I've written a class that has a templated member function, mostly because it takes a std::vector as an argument, however I'm struggling to find a proper way to call it.
class foo(){
// ...
template <typename _t> int bar(const std::vector<_t> *values);
// ...
}
when calling this function later with:
// ...
foo c;
std::vector<int> v(5,100);
c.bar(&v);
// ...
I get the error:
error: no matching function for call to ‘foo::bar(std::vector<int>*)’
c.bar(&v);
Shouldn't foo::bar(std::vector<int>*) conform to the template parameters? Why won't it compile?
Working example:
#include <vector>
class foo{
public:
template <typename _t> int bar(const std::vector<_t> *values) {
return 1;
}
};
int main() {
foo c;
std::vector<int> v(5,100);
c.bar(&v);
}
If you really need it to not to be inline you can:
//from here
#include <vector>
class foo{
public:
template <typename _t> int bar(const std::vector<_t> *values);
};
template <typename _t> int foo::bar(const std::vector<_t> *values) {
return 0;
}
//to here - should be in header file to allow compiler to link it!
int main() {
foo c;
std::vector<int> v(5,100);
c.bar(&v);
}
I need some Help with this small code that includes re-def of operator and Template
But I keep getting this error:
error C2955 use of class template requires template argument list
#include<iostream>
using namespace std;
template <class T>
class student
{
friend int operator+(student &other1,student &other2);
public:
student(T g);
private:
int grade;
};
template <class T>
student<T>::student(T g)
{
grade=g;
}
void main()
{
student<int> s1(40),s2(90);
int sum;
sum=s1+s2;
cout<<"average="<<sum/2.0<<endl;
}//main
template <class T>
int operator+(student &other1,student &other2)
{
return other1.grade+other2.grade;
}
You need to say
template<class T>
int operator+(student<T> a, student<T> b)
...
You were missing the T
Good evening everyone!
I'm stuck with an itchy problem. Say I have the following code :
#include <iostream>
template <class T>
struct MyTemplate {
int _array[sizeof (T)];
} ;
struct MyStruct {
struct MyNestedStruct {
int foo;
} ;
MyTemplate<MyNestedStruct> _nested;
} ;
int main(int, char **) {
return 0;
}
This example snippet compiles fine. What I would like to do is lift the definition of MyNestedStruct out of MyStruct :
#include <iostream>
template <class T>
struct MyTemplate {
int _array[sizeof (T)];
} ;
struct MyStruct {
struct MyNestedStruct;
MyTemplate<MyNestedStruct> _nested;
} ;
struct MyStruct::MyNestedStruct {
int foo;
} ;
int main(int, char **) {
return 0;
}
Of course this one doesn't compile since I'm requesting the size of a partially declared type (error: invalid application of ‘sizeof’ to incomplete type ‘MyStruct::MyNestedStruct’).
My real use case does need sizeof, but will also use several MyNestedClass-like template parameters in that fashion, each fully declared with constructors and the like. For this reason I don't want MyClass to get bloated. Can I do anything about it, or will I have to resort to an external scope (namespace) to put my "inner" classes in ?
Unless...
struct MyStruct {
#include "MyNestedStruct.h" // Dirty preprocessor to the rescue !
MyTemplate<MyNestedStruct> _nested;
} ;
Ugh.
Essentially we need to defer template instantiation of MyTemplate since that's the one that requires T to be complete. The trick I can see to do that here is to templatize MyStruct.
template <typename T>
struct MyTemplate {
int _array[sizeof(T)];
};
template <typename Dummy = void>
struct MyStruct {
struct MyNestedStruct;
MyTemplate<MyNestedStruct> _nested;
};
template <typename Dummy>
struct MyStruct<Dummy>::MyNestedStruct {
int foo;
};
int main() {}
Now we've deferred the instantiation of MyStruct, but we need to use MyStruct<> instead. If that's unsatisfactory, then just provide a type alias.
#include <iostream>
template <typename T>
struct MyTemplate {
int _array[sizeof(T)];
};
template <typename Dummy = void>
struct MyStructImpl {
struct MyNestedStruct;
MyTemplate<MyNestedStruct> _nested;
};
template <typename Dummy>
struct MyStructImpl<Dummy>::MyNestedStruct {
int foo;
};
using MyStruct = MyStructImpl<>;
int main() {
MyStruct s;
std::cout << sizeof(s._nested._array) << std::endl;
}
Prints 16.
Note: you could also to hide MyStructImpl in a detail namespace or something similar.
I found this example of another template passed as parameter to a template:
template<template<typename T> class AllocatePolicy>
struct Pool {
void allocate(size_t n) {
int *p = AllocatePolicy<int>::allocate(n);
}
};
template<typename T>
struct allocator { static T * allocate(size_t n) { return 0; } };
int main()
{
// pass the template "allocator" as argument.
Pool<allocator> test;
return 0;
}
This seems perfectly reasonable to me but MSVC2012 compiler is complaining that "allocator: ambiguous symbol"
Is this a compiler-problem or is there something wrong with this code?
You most likely have an evil:
using namespace std;
Somewhere in your code, which makes your class template allocator clash with the std::allocator Standard allocator.
For instance, this code does not compile unless you comment the line containing the using directive:
#include <memory>
// Try commenting this!
using namespace std;
template<template<typename T> class AllocatePolicy>
struct Pool {
void allocate(std::size_t n) {
int *p = AllocatePolicy<int>::allocate(n);
}
};
template<typename T>
struct allocator { static T * allocate(std::size_t n) { return 0; } };
int main()
{
Pool<allocator> test;
}