Consider I have a class template which takes an array as an argument:
template <int N, const float numbers[N]>
class TemplateClass
{
public:
TemplateClass()
{
for (int i = 0; i < N; i++)
{
cout << numbers[i] << endl;
}
}
};
I can use it successfully like this:
const int N = 3;
extern const float Constants[N];
const float Constants[N] = { 2.0f, 2.1f, 2.2f };
int main()
{
TemplateClass<3, Constants>();
return 0;
}
However, my attempts at moving the constructor method body outside of the class declaration were in vain:
// Fails with:
// error C2440: 'specialization' : cannot convert from 'const float *' to 'const float [3]'
template <int N, const float numbers[N]>
TemplateClass<N, numbers>::TemplateClass()
{
for (int i = 0; i < N; i++)
{
cout << numbers[i] << endl;
}
}
// Fails with:
// error C3860: template argument list following class template name must list parameters in the order used in template parameter list
// error C3855: 'TemplateClass<N,numbers>': template parameter 'numbers' is incompatible with the declaration
template <int N, const float* numbers>
TemplateClass<N, numbers>::TemplateClass()
{
for (int i = 0; i < N; i++)
{
cout << numbers[i] << endl;
}
}
This is observed on both VC++11 and VC++12 compilers. How do I solve this?
Reason/Bug:
According to the standard §14.1/4, non-type template-parameter must have one of the following types:
Integral or enumeration type,
Pointer to object or pointer to function,
lvalue reference to object or lvalue reference to function,
pointer to member,
std::nullptr_t.
const float numbers[N] is none of the above. See also (https://stackoverflow.com/a/16214727/2352671)
Now the question that still remains is why when you define the constructor in-line (i.e., inside class's definition) your program compiles and runs fine.
The answer to this question is that Non-type template parameters that are declared as arrays or functions are converted to pointers or pointers to functions, respectively. We can confirm this by printing the type
of numbers inside the in-lined constructor:
template <int N, const float numbers[N]>
class TemplateClass
{
public:
TemplateClass()
{
std::cout << typeid(numbers).name() << std::endl;
for (int i = 0; i < N; i++)
{
std::cout << numbers[i] << std::endl;
}
}
};
The output we are getting is:
float const *
As such, the standards aren't being violated and the code works.
The next question we have to answer is why when you define the constructor outside class's definition with the template list of parameters as template <int N, const float *numbers>
you get a compiler error.
The answer to this question is because the list of parameters in you class definition (i.e., template <int N, const float numbers[N]>) and the list of parameters in your construction's definition do not match.
Solution:
#include <iostream>
using namespace std;
template <int N, const float* numbers>
class TemplateClass
{
public:
TemplateClass();
};
template <int N, const float *numbers>
TemplateClass<N, numbers>::TemplateClass()
{
for (int i = 0; i < N; i++)
{
cout << numbers[i] << endl;
}
}
const int N = 3;
extern const float Constants[N];
const float Constants[3] = { 2.0f, 2.1f, 2.2f };
int main()
{
TemplateClass<3, Constants>();
return 0;
}
Output:
2
2.1
2.2
the template methods must be defined in the same file header of the template class. A template is a declaration only, It is instantiated by compiler when you use it for your variable, so the template methods cannot be implemented in a cpp file.
Related
Consider the code below
#include <iostream>
#include <functional>
class Solver{
public:
int i = 0;
void print(){
std::cout << "i solved" << std::endl;
}
};
template <typename T> class ThingHandler{
public:
template <typename B,typename C>
void handleThing(T& solver,B paramOne,C paramTwo){
std::cout << "i handled something " << std::endl;
solver.print();
std::cout << paramOne << paramTwo;
}
};
class CantHandle{
public:
void needHelp(std::function<void(int,int)> handleThing){
int neededInt = 0;
int neededIntTwo = 2;
handleThing(neededInt,neededInt);
}
};
int main() {
ThingHandler<Solver> thingHandler;
CantHandle cantHandle;
Solver solver;
solver.i = 10;
auto fp = std::bind(&ThingHandler<Solver>::handleThing<Solver,int,int>,
thingHandler,solver,std::placeholders::_1,std::placeholders::_1);
//the row above is what I want to achieve
cantHandle.needHelp(fp);
return 0;
}
I'm getting the following error:
140: error: no matching function for call to ‘bind(, ThingHandler&, Solver&, const
std::_Placeholder<1>&, const std::_Placeholder<1>&)’ 37 | auto
fp = std::bind(&ThingHandler::handleThing,
thingHandler,solver,std::placeholders::_1,std::placeholders::_1);
What I want to do is have a generic class that solves some problem. Then call upon a specialization of that class. So in the case above I want ThingHandler to be (Solver& solver, int paramOne, int paramTwo). I'm not quite sure how to achieve this.
Member function you bind takes two template type parameters, so Solver is redundant in template argument list.
Should be:
&ThingHandler<Solver>::handleThing<int,int>
Some remarks: your code binds handleThing for a copy of thingHandler instance.
Also first bound parameter - solver, is copied into functor generated by bind.
If you want to avoid these two copies, use & or std::ref:
auto fp = std::bind(&ThingHandler<Solver>::handleThing<int,int>,
&thingHandler,std::ref(solver),std::placeholders::_1,std::placeholders::_2);
I have a struct and template class, within which there is a function that should check if T is equal to the struct and if so, do something.
The struct:
struct mystruct
{
int x;
int y;
int z;
};
the template class:
template <typename T>
class myclass
{
public:
void myfunc()
{
// this condition is ignored..
if(std::is_same<T,mystruct>::value==0)
{
cout << "T is not mystruct type" << '\n';
}
else
{
T ms;
ms.x = 5;
ms.y = 4;
ms.z = 3;
}
}
};
in main function, if T == mystruct everything goes through fine:
int main()
{
// no issues
myclass<mystruct> x;
x.myfunc();
}
but if T != mystruct:
int main()
{
//tries to unsuccessfuly convert int to mystruct
myclass<int> x;
x.myfunc();
}
execution fails with the below error:
error: request for member 'x' in 'ms', which is of non-class type 'int'
ms.x = 5;
does anyone have an idea why the if-else statement not working as expected?
Thanks!
Even if the if condition evaluates to false, for a particular template instantiation, the entire template still must consist of valid C++ code.
If the template's parameter is int, for example, then the else part of the if statement becomes equivalent to:
else
{
int ms;
ms.x = 5;
ms.y = 4;
ms.z = 3;
}
It should be obvious why this won't compile. Because the entire template becomes, equivalent to:
if (true)
{
cout << "T is not mystruct type" << '\n';
}
else
{
int ms;
ms.x = 5;
ms.y = 4;
ms.z = 3;
}
Even though else never gets executed, it stlil must be valid C++ code. Templates are no different.
C++17 introduced if constexpr which requires that the evaluated if expression is constant, and only the appropriate part of the if statement ends up being compiled, with the rest being effectively discarded. So, with C++17, you should be able to change the if statement to if constexpr, and get the expected results.
I am trying to design a class which all its data is constant and know at compile time. I could just create this by manually typing it all but I want to use a template so that I don't have to rewrite almost the same code many times.
I was thinking templates are the way to do this e.g
template<class T> class A { ... }
A<float>
A<MyObject>
A<int>
But then I wasn't sure how I could get the constant data that I know into this object. I could do it at run-time with a member function which does a switch statement on the type or something similar but I ideally want it to effectively be a dumb data holder for me to use.
So in the case of A<float> I would have this:
// member function
int getSize() {
return 4;
}
Instead of (pseudo code)
// member function
int getSize() {
if (type == float) {
return 4;
} else if ...
}
I'm wondering if there is a known way to do this? I don't have any experience with constexpr, could that be the key to this?
edit: To clarify: I want member functions which always return the same result based on the templated type/class. For example, A would always return 4 from getSize() and 1 from getSomethingElse() and 6.2 from getAnotherThing(). Where as A would return 8 from getSize() and 2 from getSomethingElse() and 8.4 from getAnotherThing().
You can have this template
template <int size_, int foo_, int bar_>
struct MyConstData {
static const int size = size_; // etc
};
Then specialize your template:
template <class T> class A;
template <> class A<float> : MyConstData<13,42,-1> {};
template <> class A<double> : MyConstData<0,0,42> {};
You can specialize particular functions within a class, and given your description of things, I suspect that's what you want. Here is an example of how this works:
#include <iostream>
#include <string>
template <class T>
class A {
public:
int MyConstantFunction() const { // Default implementation
return 0;
}
};
template <>
int A<int>::MyConstantFunction() const
{
return 3;
}
template <>
int A<float>::MyConstantFunction() const
{
return 5; // If you examine the world, you'll find that 5's are everywhere.
}
template <>
int A<double>::MyConstantFunction() const
{
return -5;
}
int main(int, char *[])
{
using ::std::cout;
A<int> aint;
A<float> afloat;
A<long> along;
cout << "aint.MyConstantFunction() == " << aint.MyConstantFunction() << '\n';
cout << "afloat.MyConstantFunction() == "
<< afloat.MyConstantFunction() << '\n';
cout << "along.MyConstantFunction() == "
<< along.MyConstantFunction() << '\n';
return 0;
}
Notice how along just used the default implementation from the class declaration. And this highlights a danger here. If the translation unit using your specialization for a given type hasn't seen that specialization, it won't use it, and that may cause all kinds of interesting problems. Make sure this happens.
The other option is to not provide a default implementation at all, and so you get an instantiation error.
My gut feeling is that you are doing something that is pointless and a poor design. But, since I don't know the full context I can't say that for sure. If you insist on doing this, here's how.
If you want to implement different things depending on the type, you could try this:
template <class T>
class Foo {
T data;
string toString() {
return myGeneralToString(data);
}
};
template <>
class Foo<string> {
string data;
string toString() {
return "Already a string: " + data;
}
};
If you just want templated constants, I'd try this:
template <int a, int b>
class Calc {
public:
static constexpr int SUM = a + b;
};
int main()
{
std::cout << Calc<3, 5>::SUM << std::endl;
return 0;
}
Edit: as pointed out by Omnifarious C++14 has templated constants without templating the class itself. So you could simplify the example to:
class Calc {
public:
template <int a, int b>
static constexpr int SUM = a + b;
};
int main()
{
std::cout << Calc::SUM<3, 5> << std::endl;
return 0;
}
I want to use SFINAE to stop from explicitly calling the destructor because MSVS 2010 considers it an error when done on a builtin type pointer.
How would I do this?
You might look at it from the wrong angle: You shouldn't exclude what does not work, you should detect what does work. In your case, you are trying to check if a given type T is a class and hence you could call the destructor.
That said, you want std::is_class. If it is not available for your compiler, there is Boost.TypeTraits' boost::is_class available which works with VC++ 8 and newer.
This shows how to specialize a function so it is called for fundamental data types in C++.
template < class T>
void delete_object(T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = 0) {
// Do nothing because this is not an object
}
template<class T>
void delete_object(T* object) {
delete object;
}
int main()
{
int arithmetic1 = 1;
delete_object(arithmetic1);
float arithmetic2 = 1;
delete_object(arithmetic2);
Object* object1 = new Object();
delete_object(object1);
return 0;
}
Here are the other fundamental tests
std::is_integral<> - 'char' up to 'long long'
std::is_floating_point - 'float' up to 'long double'
std::is_signed<> - signed types
std::is_unsigned<> - unsigned types
std::is_arithmetic - is_integral<> OR is_floating_point<>
std::is_fundamental<> - is_arithmetic<> OR 'void'
With the following type function we can determine whether a type is a class type:
// traits/isclasst.hpp
template<typename T>
class IsClassT {
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename C> static One test(int C::*);
template<typename C> static Two test(…);
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};
This template uses SFINAME principle.
The following program uses this type function to test whether certain types and objects are class types:
// traits/isclasst.cpp
#include <iostream>
#include "isclasst.hpp"
class MyClass {
};
struct MyStruct {
};
union MyUnion {
};
void myfunc()
{
}
enumE{e1}e;
// check by passing type as template argument
template <typename T>
void check()
{
if (IsClassT<T>::Yes) {
std::cout << " IsClassT " << std::endl;
}
else {
std::cout << " !IsClassT " << std::endl;
}
}
// check by passing type as function call argument
template <typename T>
void checkT (T)
{
check<T>();
}
int main()
{
std::cout << "int: ";
check<int>();
std::cout << "MyClass: ";
check<MyClass>();
std::cout << "MyStruct:";
MyStruct s;
checkT(s);
std::cout << "MyUnion: ";
check<MyUnion>();
std::cout << "enum: ";
checkT(e);
std::cout << "myfunc():";
checkT(myfunc);
}
The program has the following output:
int: !IsClassT
MyClass: IsClassT
MyStruct: IsClassT
MyUnion: IsClassT
enum: !IsClassT
myfunc(): !IsClassT
I want to extract the return type of a function. Problem is, there are other functions with the same name but different signature, and I can not get C++ to select the appropriate one. I know about std::result_of, but from a few tries I have concluded it suffers from the same problem as well. I have heard about a solution involving decltype as well, but I do not know any specifics.
At the moment I am using template metaprogramming to extract the return type from a function pointer type, which works fine for a limited number of parameters (any non-limited solution?), given that extraction of function pointer type works for unambiguous functions.
#include <iostream>
using namespace std;
// ----
#define resultof(x) typename ResultOf<typeof(x)>::Type // might need a & before x
template <class T>
class ResultOf
{
public:
typedef void Type; // might need to be T instead of void; see below
};
template <class R>
class ResultOf<R (*) ()>
{
public:
typedef R Type;
};
template <class R, class P>
class ResultOf<R (*) (P)>
{
public:
typedef R Type;
};
// ----
class NoDefaultConstructor
{
public:
NoDefaultConstructor (int) {}
};
int f ();
int f ()
{
cout << "f" << endl;
return 1;
}
double f (int x);
double f (int x)
{
cout << "f(int)" << endl;
return x + 2.0;
}
bool f (NoDefaultConstructor);
bool f (NoDefaultConstructor)
{
cout << "f(const NoDefaultConstructor)" << endl;
return false;
}
int g ();
int g ()
{
cout << "g" << endl;
return 4;
}
int main (int argc, char* argv[])
{
if(argc||argv){}
// this works since there is no ambiguity. does not work without &
// resultof(&g) x0 = 1;
// cout << x0 << endl;
// does not work since type of f is unknown due to ambiguity. same thing without &
// resultof(&f) x1 = 1;
// cout << x1 << endl;
// does not work since typeof(f()) is int, not a member function pointer; we COULD use T instead of void in the unspecialized class template to make it work. same thing with &
// resultof(f()) x2 = 1;
// cout << x2 << endl;
// does not work per above, and compiler thinks differently from a human about f(int); no idea how to make it correct
// resultof(f(int)) x3 = 1;
// cout << x3 << endl;
// does not work per case 2
// resultof(f(int())) x4 = 1;
// cout << x4 << endl;
// does not work per case 2, and due to the lack of a default constructor
// resultof(f(NoDefaultConstructor())) x5 = 1;
// cout << x5 << endl;
// this works but it does not solve the problem, we need to extract return type from a particular function, not a function type
// resultof(int(*)(int)) x6 = 1;
// cout << x6 << endl;
}
Any idea what syntax feature am I missing and how to fix it, preferably with a solution that works in a simple way, e.g. resultof(f(int))?
I think that this can be done with decltype and declval:
For example: decltype(f(std::declval<T>())).
It's very hard to inspect an overloaded function name without arguments. You can inspect the return types for overloads that differ in arity -- provided that no arity has more than one overload. Even then, turning a hard error (if/when a given arity does have more than one overload) into SFINAE is a pain as it requires writing a trait just for that particular function(!) since overloaded function names can't be passed as any kind of argument. Might as well require user code to use an explicit specialization...
template<typename R>
R
inspect_nullary(R (*)());
template<typename R, typename A0>
R
inspect_unary(R (*)(A0));
int f();
void f(int);
int g();
double g();
typedef decltype(inspect_nullary(f)) nullary_return_type;
typedef decltype(inspect_unary(f)) unary_return_type;
static_assert( std::is_same<nullary_return_type, int>::value, "" );
static_assert( std::is_same<unary_return_type, void>::value, "" );
// hard error: ambiguously overloaded name
// typedef decltype(inspect_nullary(g)) oops;
Given that you're using C++0x, I feel the need to point out that there is (IMO) never a need to inspect a return type beyond typename std::result_of<Functor(Args...)>::type, and that doesn't apply to function names; but perhaps your interest in this is purely academical.
Okay, after a few attempts I managed to work around the std::declval method suggested by Mankarse. I used a variadic class template to fixate the parameters, and used the template deduction of functions to get the return value from a function pointer. Its current syntax is typeof(ResultOf<parameters>::get(function)), unfortunately it is still far from the desired resultof<parameters>(function) form. Will edit this answer if I find a way to further simplify it.
#include <iostream>
#include <typeinfo>
using namespace std;
template <class... Args>
class ResultOf
{
public:
template <class R>
static R get (R (*) (Args...));
template <class R, class C>
static R get (R (C::*) (Args...));
};
class NoDefaultConstructor
{
public:
NoDefaultConstructor (int) {}
};
int f ();
double f (int x);
bool f (NoDefaultConstructor);
int f (int x, int y);
int main (int argc, char* argv[])
{
if(argc||argv){}
cout << typeid(typeof(ResultOf<>::get(f))).name() << endl;
cout << typeid(typeof(ResultOf<int>::get(f))).name() << endl;
cout << typeid(typeof(ResultOf<NoDefaultConstructor>::get(f))).name() << endl;
cout << typeid(typeof(ResultOf<int, int>::get(f))).name() << endl;
typeof(ResultOf<int>::get(f)) d = 1.1;
cout << d << endl;
}
Edit:
Managed to solve it with variadic macros, the syntax is now resultof(f, param1, param2, etc). Without them I couldn't pass the commas between the parameter types to the template. Tried with the syntax resultof(f, (param1, param2, etc)) to no avail.
#include <iostream>
using namespace std;
template <class... Args>
class Param
{
public:
template <class R>
static R Func (R (*) (Args...));
template <class R, class C>
static R Func (R (C::*) (Args...));
};
#define resultof(f, ...) typeof(Param<__VA_ARGS__>::Func(f))
int f ();
double f (int x);
int f (int x, int y);
int main (int argc, char* argv[])
{
resultof(f, int) d = 1.1;
cout << d << endl;
}