I am trying to implement a vector (in the math sense) using templates. I would like to define standard vector constants in the class. I managed to do it for simple constants (all zeroes, all ones) but I am now struggling to define the more difficult unit vectors (all zeroes except one component set to one at given index).
I did not yet find an elegant way to do that. Here is how I would like to define that:
#include <iostream>
template<unsigned int tSize, typename tReal>
class Vector {
public:
template<unsigned int tIndex>
static const Vector msUnit;
inline Vector () {}
template<typename...tTypes>
inline Vector (tTypes...pVals) {
set(mReals, pVals...);
}
inline tReal operator[] (unsigned int pIndex) {
return mReals[pIndex];
}
inline const tReal operator[] (unsigned int pIndex) const {
return mReals[pIndex];
}
protected:
template<typename tType>
void set (tReal* pPtr, const tType pVal) {
*pPtr = pVal;
}
template<typename tType, typename...tTypes>
void set (tReal* pPtr, const tType pVal, const tTypes...pVals) {
*pPtr = pVal;
set(pPtr+1, pVals...);
}
tReal mReals [tSize];
};
int main() {
Vector<3,double> lVec = Vector<3,double>::msUnit<2>;
std::cout << "Vector: (" << lVec[0] << ", " << lVec[1] << ", " << lVec[2] << ")" << std::endl;
return 0;
}
But I have not found a way to define the msUnit static const member template.
I tried this:
template<unsigned int tIndex, unsigned int tSize, typename tReal>
const Vector<tSize,tReal> Vector<tSize,tReal>::msUnit<tIndex>;
But compilers (clang & gcc) complain:
prog.cc:43:48: error: nested name specifier 'Vector<tSize, tReal>::' for declaration does not refer into a class, class template or class template partial specialization
const Vector<tSize,tReal> Vector<tSize,tReal>::msUnit<tIndex>;
~~~~~~~~~~~~~~~~~~~~~^
prog.cc:43:54: error: expected ';' at end of declaration
const Vector<tSize,tReal> Vector<tSize,tReal>::msUnit<tIndex>;
^
;
prog.cc:43:54: error: expected unqualified-id
Here is a live example of this test: http://melpon.org/wandbox/permlink/AzbuATU1lbjXkksX
Is it even possible to have static const template variable members in template classes ? And if so how ?
And I still have to find a way to provide an initializer for the msUnit template.
You already found the way how you can decleare your msUnit - you have to use two templates, i.e.
template<unsigned tSize, typename tReal>
template<unsigned tIndex>
const Vector<tSize, tReal> Vector<tSize, tReal>::msUnit;
As you have currently no matching constructor for initializing the n'th argument to one and all others to zero (which wouldn't make sense I guess), you can just use your own function. As you already access a static member of your class, you also have access to your complete class, so you can just use
template<unsigned int tSize, typename tReal>
class Vector {
public:
// ...
template<unsigned int tIndex>
static const Vector msUnit;
private:
static const Vector<tSize, tReal> createUnitVector(unsigned tIndex) {
Vector<tSize, tReal> v{};
v.mReals[tIndex] = tReal(1);
return v;
}
tReal mReals [tSize];
};
template<unsigned tSize, typename tReal>
template<unsigned tIndex>
const Vector<tSize, tReal> Vector<tSize, tReal>::msUnit{Vector::createUnitVector(tIndex)};
So everything as you already have it, but you initialize your vector with some other function given in your class.
Here you go for the live demo: http://melpon.org/wandbox/permlink/5b7cgXTeqXZDoCRp
Related
I want to define a class, called Nested here, that will contains two or more (one here) data members that support arithmetic operations using expression templates, for example an std::valarray. For this class itself, I am defining its own expression templates and I want to "forward" the arithmetic operations down to the members.
A minimal (non)working example is given below:
#include <iostream>
#include <valarray>
template <typename E>
struct NestedExpr {
operator const E& () const {
return *static_cast<const E*>(this);
}
};
template <typename A>
class Nested : public NestedExpr <Nested<A>>{
private:
A a;
public:
Nested(const A& _a) : a(_a) {}
template <typename E>
inline Nested<A>& operator = (const NestedExpr<E>& _expr) {
const E& expr(_expr);
a = expr.get_a();
return *this;
}
inline A& get_a() { return a; }
inline const A& get_a() const { return a; }
};
// ================================================================= //
template <typename ARG, typename S>
class NestedMul : public NestedExpr<NestedMul<ARG, S>> {
public:
const ARG& arg;
const S s;
NestedMul(const ARG& _arg, S _s) : arg(_arg), s(_s) {}
inline auto get_a() const { return arg.get_a() * s; };
};
template< typename ARG, typename S>
inline NestedMul<ARG, S> operator * (S s, const NestedExpr<ARG>& arg) {
return {arg, s};
}
// ================================================================= //
template <typename ARG1, typename ARG2>
class NestedAdd : public NestedExpr<NestedAdd<ARG1, ARG2>> {
public:
const ARG1& arg1;
const ARG2& arg2;
NestedAdd(const ARG1& _arg1, const ARG2& _arg2)
: arg1(_arg1), arg2(_arg2) {}
inline auto get_a() const { return arg1.get_a() + arg2.get_a(); };
};
template<typename ARG1, typename ARG2>
inline NestedAdd<ARG1, ARG2>
operator + (const NestedExpr<ARG1>& arg1, const NestedExpr<ARG2>& arg2) {
return {arg1, arg2};
}
int main () {
std::valarray<double> x1 = {4.0};
std::valarray<double> x2 = {3.0};
std::valarray<double> x3 = {0.0};
std::valarray<double> x4 = {0.0};
auto a = Nested<std::valarray<double>>(x1);
auto b = Nested<std::valarray<double>>(x2);
auto c = Nested<std::valarray<double>>(x3);
// this returns 21
c = 2*a + 3*b;
std::cout << c.get_a()[0] << std::endl;
// works as expected, returns 17
x4 = 2*x1 + 3*x2;
std::cout << x4[0] << std::endl;
}
The output of this program is
21
17
i.e. forwarding the expression down to the member does not seem to provide the expected result obtained directly from using the valarrays.
Any help here is appreciated.
In the below function definition:
inline auto get_a() const { return arg.get_a() * s; };
your expected behavior is that auto deduces std::valarray<double>, that is, the result type of a multiplication of std::valarray<double> and int which is a new object that already stores values multiplied by the integer.
This is how operator* is defined [valarray.binary]/p2:
template <class T>
valarray<T> operator*(const valarray<T>&,
const typename valarray<T>::value_type&);
However, there's the following paragraph in the standard [valarray.syn]/p3:
Any function returning a valarray<T> is permitted to return an object of another type, provided all the const member functions of valarray<T> are also applicable to this type. This return type shall not add more than two levels of template nesting over the most deeply nested argument type.
This type must be convertible to std::valarray<double>, but itself, for optimization purposes, may not represent the actual result before that conversion happens.
That is, here's the actual type deduced for auto by GCC:
std::_Expr<std::__detail::_BinClos<std::__multiplies
, std::_ValArray
, std::_Constant, double, double>, double>
and here's what Clang uses:
std::__1::__val_expr<std::__1::_BinaryOp<std::__1::multiplies<double>,
std::__1::valarray<double>, std::__1::__scalar_expr<double> > >
In other words, you are returning by value an object which probably defers the actual computations. In order to do so, those intermediate objects need to store somehow the deferred subexpressions.
Inspecting GCC libstdc++'s implementation, one can find the following representation:
template <class _Oper, class _FirstArg, class _SecondArg>
class _BinBase
{
public:
typedef typename _FirstArg::value_type _Vt;
typedef typename __fun<_Oper, _Vt>::result_type value_type;
_BinBase(const _FirstArg& __e1, const _SecondArg& __e2)
: _M_expr1(__e1), _M_expr2(__e2) {}
// [...]
private:
const _FirstArg& _M_expr1;
const _SecondArg& _M_expr2;
};
Note that subexpressions are stored as references. This means that in the definition of get_a():
return arg1.get_a() + arg2.get_a();
_M_expr1 and _M_expr2 are bound to temporary objects:
arg1.get_a()
arg2.get_a()
i.e., intermediate objects which are the results of multiplications, whose lifetime ends as soon as NextedAdd::get_a() exits, leading to undefined behavior when the result is eventually computed, in particular, when the implementation attempts to access each individual element of that intermediate subexpressions:
value_type operator[](size_t __i) const
{
return _Oper()(_M_expr1[__i], _M_expr2[__i]);
}
A quick solution would be to use the following return type:
std::decay_t<decltype(arg.get_a())> get_a() const { return arg.get_a() * s; }
This will recursively ensure that the final result type of any operation will be whatever the original type T in Nested<T> was, i.e., std::valarray<double>.
DEMO
There are a few questions on SO that address passing function pointers as parameters/arguments (here, here, here, etc.). In fact, I asked a related question the other day. However, this question is a little different.
My problem is that I am writing a class that I want to be extremely flexible.
What I have now works for non-member functions. It is posted below
template <typename T>
class MyClass
{
private:
typedef double (*firstFunctionPtr) (const T &var);
typedef bool (*secondFunctionPtr)(const T &var);
// Function pointers as member variables
firstFunctionPtr _firstFunc;
secondFunctionPtr _secondFunc;
public:
inline MyClass(firstFunctionPtr firstFunc,
secondFunctionPtr secondFunc);
};
template<typename T>
MyClass<T>::MyClass(firstFunctionPtr firstFunc, secondFunctionPtr secondFunc) :
_firstFunc(firstFunc),
_secondFunc(secondFunc),
{}
However, this falls apart when I need to initialize with a pointer to a member function of some other, arbitrary, class, which, unfortunately for me, happens to be a common use case for my purposes.
This answer suggests that
In a proper C++ interface you might want to have a look at having your function take templated argument for function objects to use arbitrary class types.
However, I have not been able to make this compile. I've tried templating my typedefs (using the C++11 aliasing approach), and I've tried adding a second template parameter to the class to handle the calling class of those member functions, but neither approach has worked.
This Q/A seems to be getting towards what I'm trying to do, but I can't make heads or tails of it.
Can someone please explain how I might modify my class to handle arbitrary member functions pointers being passed in?
Furthermore, is it possible to make it so that it can handle either arbitrary member functions or non-member functions?
Lastly, is it possible to do this with templates?
For the record, I'm trying to avoid using the functional header, but it may be a fool's errand not to use it.
If you want MyClass to be a template that can hold both free function
pointers of types:
double (*)(const T &var);
bool (*)(const T &var);
for some parameter type T, or alternatively member-function
pointers of types:
double (C::*)(const T &var);
bool (C::*)(const T &var);
for some parameter types C and T then, MyClass must be parameterized
by both T and C and you require two specializations:
Where C is some non-class type
Where C is any class type
In case (1), the non-class type C cannot possibly have member functions,
so that one will implement the free-function pointer specialization.
In case (2), the class C could be one that has member functions, so that one
will implement the member-function pointer specialization.
The obvious choice for a non-class type C is void. So we can make C
default to void:
Primary template
template<typename T, typename C = void>
struct MyClass;
So that:
MyClass<T>
will be the free function pointer specialization for T, and:
MyClass<T,C>
for any C other than void, will be the member-function pointer specialization.
As you may know you can use std::enable_if
and SFINAE to make the compiler
chose one specialization of a class template or another, depending on whether one
of its template parameters U satisfies some compiletime test. You could take
that approach here, but another one is available that does not require that apparatus:
Starting with the primary template, we would just like to have:
Free function specialization
template<typename T>
struct MyClass<T>
{
... for free function pointers ...
};
and:
Member function specialization
template<typename T, typename C>
struct MyClass<T,C>
{
... for member function pointers ...
};
But we can't have just that, because the member function "specialization" has exactly
the same template parameters as the primary template. Which means it isn't
a specialization, and the compiler won't allow it.
You can easily remove that problem, however, simply by giving the primary
template one more defaulting template parameter that it doesn't need, but whose
presence allows both those specializations to stand.
New primary template
template <typename T, typename C = void, typename Default = void>
struct MyClass;
So here is an illustrative solution:
// Primary template
template <typename T, typename C = void, typename Default = void>
struct MyClass;
// Free function specialization
template <typename T>
struct MyClass<T>
{
using firstFunctor_t = double(*)(T const &);
using secondFunctor_t = bool(*)(T const &);
MyClass(firstFunctor_t firstFunc, secondFunctor_t secondFunc)
: _firstFunc(firstFunc),
_secondFunc(secondFunc)
{}
double callFirst(T const & var) {
return _firstFunc(var);
}
bool callSecond(T const & var) {
return _secondFunc(var);
}
private:
firstFunctor_t _firstFunc;
secondFunctor_t _secondFunc;
};
// Member function specialization
template <typename T, typename C>
struct MyClass<T,C>
{
using firstFunctor_t = double(C::*)(T const &);
using secondFunctor_t = bool(C::*)(T const &) const;
MyClass(firstFunctor_t firstFunc, secondFunctor_t secondFunc)
: _firstFunc(firstFunc),
_secondFunc(secondFunc)
{}
double callFirst(C & obj, T const & var) {
return (obj.*_firstFunc)(var);
}
double callFirst(C const & obj, T const & var) {
auto & o = const_cast<C&>(obj);
return (o.*_firstFunc)(var);
}
bool callSecond(C & obj, T const & var) {
return (obj.*_secondFunc)(var);
}
bool callSecond(C const & obj, T const & var) {
auto & o = const_cast<C&>(obj);
return (o.*_secondFunc)(var);
}
private:
firstFunctor_t _firstFunc;
secondFunctor_t _secondFunc;
};
In the member function specialization, notice a couple of points that you might
not have considered:-
I decided that the second member function I want to store shall be a
const member function. It's more than likely that a member function of C
that take a T const & argument and returns bool will be a const member
function, isn't it? And if so, then that const-ness has to be part of
the member-function type definition that I use in the specialization:
using secondFunctor_t = bool(C::*)(T const &) const;
or attempts to instantiate the specialization with any bool (C::*)(T const &) const
will fail to compile.
Also, I have provided two overloads for each of MyClass<T,C>::callFirst
and MyClass<T,C>::callSecond, one with arguments:
C & obj, T const & var
and another with arguments:
C const & obj, T const & var
Without the second, attempts to call either MyClass<T,C>::callFirst
or MyClass<T,C>::callSecond with an obj that is const will fail to
compile.
For program to demo this solution you can append:
#include <iostream>
#include <string>
double foo(std::string const & s)
{
return std::stod(s);
}
bool bar(std::string const & s)
{
return s.size() > 0;
}
struct SomeClass
{
SomeClass(){};
double foo(std::string const & s) {
return ::foo(s);
}
bool bar(std::string const & s) const {
return ::bar(s);
}
};
int main()
{
MyClass<std::string> my0{foo,bar};
std::cout << std::boolalpha;
std::cout << my0.callFirst("1.11") << std::endl;
std::cout << my0.callSecond("Hello World") << std::endl;
MyClass<std::string,SomeClass> my1{&SomeClass::foo,&SomeClass::bar};
SomeClass thing;
std::cout << my1.callFirst(thing,"2.22") << std::endl;
std::cout << my1.callSecond(thing,"Hello World") << std::endl;
SomeClass const constThing;
std::cout << my1.callFirst(constThing,"3.33") << std::endl;
std::cout << my1.callSecond(constThing,"Hello World") << std::endl;
return 0;
}
See it live
You said that you want this template to be "extremely flexible". The
illustrated solution is fitted to your example, but you might be
interested in know that it isn't nearly as flexible as you could get.
For both free functions and member functions, with additional variadic template
parameters, your template could store and call [member] functions with
arbitary return types and arbitary numbers of arguments of arbitrary types.
See this question and
answer.
I will sugest to create a helper object which will store the type you want to work with:
template <typename RETURN, typename TYPE, typename CLASS>
struct function_pointer
{ using type_t = RETURN (CLASS::*)(const TYPE &); };
template <typename RETURN, typename TYPE>
struct function_pointer<RETURN, TYPE, std::nullptr_t>
{ using type_t = RETURN (*)(const TYPE &); };
This type will create a member-function-pointer if a class is provided as third parameter and a function-pointer otherwise. Now, we can use this helper in MyClass:
template <typename T, typename CLASS = std::nullptr_t>
class MyClass
{
using firstFunctionPtr = typename function_pointer<double, T, CLASS>::type_t;
using secondFunctionPtr = typename function_pointer<bool, T, CLASS>::type_t;
// Function pointers as member variables
firstFunctionPtr _firstFunc;
secondFunctionPtr _secondFunc;
public:
inline MyClass(firstFunctionPtr firstFunc, secondFunctionPtr secondFunc) :
_firstFunc(firstFunc),
_secondFunc(secondFunc)
{}
void call_first(CLASS &c, const T&v) { (c.*_firstFunc)(v); }
void call_second(CLASS &c, const T&v) { (c.*_secondFunc)(v); }
void call_first(const T&v) { (_firstFunc)(v); }
void call_second(const T&v) { (_secondFunc)(v); }
};
I've added call_* functions just to show a use case, which will be as below:
// Some class with the expected function signatures
struct S1
{
int i = 0;
double d(const int &) { std::cout << i << ' ' << __PRETTY_FUNCTION__ << '\n'; return{}; }
bool b(const int &) { std::cout << i << ' ' << __PRETTY_FUNCTION__ << '\n'; return{}; }
};
// Another class with the expected function signatures
struct S2
{
double d(const int &) { std::cout << __PRETTY_FUNCTION__ << '\n'; return{}; }
bool b(const int &) { std::cout << __PRETTY_FUNCTION__ << '\n'; return{}; }
};
// Free function with which could have the expected function signature
template <typename R>
R f(const int &) { std::cout << __PRETTY_FUNCTION__ << '\n'; return{}; }
Using MyClass with an arbitrary class (S1):
S1 a{1}, b{2};
S2 c, d;
MyClass<int, S1> MCiS1(&S1::d, &S1::b);
MCiS1.call_first(a, 111); // Prints -> 1 double S1::d(const int&)
MCiS1.call_second(b, 222); // Prints -> 2 bool S1::b(const int&)
MCiS1.call_first(c, 111); // Error decltype(c) is not S1.
MCiS1.call_second(d, 222); // Error decltype(d) is not S1.
Using MyClass with a different class (S2):
MyClass<int, S2> MCiS2(&S2::d, &S2::b);
MCiS2.call_first(c, 111); // Prints -> double S2::d(const int&)
MCiS2.call_second(d, 222); // Prints -> bool S2::b(const int&)
MCiS2.call_first(a, 111); // Error decltype(c) is not S2.
MCiS2.call_second(b, 222); // Error decltype(d) is not S2.
Using MyClass with non-member functions:
MyClass<int> MCi(f<double>, f<bool>);
MCi.call_first(111); // Prints -> R f(const int&) [with R = double]
MCi.call_second(222); // Prints -> R f(const int&) [with R = bool]
Check the live demo Here.
All you need to do is bind the object instance for the member function pointer as a first argument.
struct foo {
float bar1(const type &var);
bool bar2(const type &var);
};
foo my_foo;
auto f1 = std::bind(&foo::bar1, my_foo, _1);
auto f2 = std::bind(&foo::bar2, my_foo, _1);
MyClass<type> my_obj(f1, f2);
I have been playing around with template classes and constants in gcc 4.8.2 and came across an interesting linker error:
#include <iostream>
using namespace std;
template <class T, int m>
class A {
public:
static const T param = m;
T value;
A(const T &value, const T &dummy = T()) : value(value) {}
};
// Works with this
// template <class T, int m>
// const T A<T, m>::param = m;
template <class T, int m>
A<T, m> operator +(const A<T, m> &a, const A<T, m> &b) {
if (a.param != b.param) exit(1);
// Works if I replace a.param with 0
return A<T, m>(a.value + b.value, a.param);
}
int main() {
A<int, 2> v = A<int, 2>(1) + A<int, 2>(2);
cout << v.value << endl;
return 0;
}
Compiling the code in the current state gives a linker error, telling me that A::param is not defined.
Trying this code in Visual Studio 2008 as well, it compiles and links without any problems. On gcc, it compiles when I either use the external declaration of the param constant, or if I replace a.param with 0 or nothing on the line indicated.
What I do not understand is why the line containing the if statement can use a.param without compilation error, while I cannot pass a.param to the constructor without declaring it externally.
So my question is: When do I need to declare param externally, and what is the difference between the access in the if statement and the constructor call? Which of the two compilers I tested does the "right" thing here, and which one has extended the standard?
Playing around a little more, I realized it also works when I specify the -O2 flag to g++.
template <class T, int m>
class A {
public:
static const T param = m;
T value;
A(const T &value, const T &dummy = T()) : value(value) {}
};
// Works with this
// template <class T, int m>
// const T A<T, m>::param = m;
//gotta define it here!
template <class T, int m>
const T A<T, m>::param;
template <class T, int m>
A<T, m> operator +(const A<T, m> &a, const A<T, m> &b) {
if (a.param != b.param) exit(1);
// Works if I replace a.param with 0
return A<T, m>(a.value + b.value, a.param);
}
int main() {
A<int, 2> v = A<int, 2>(1) + A<int, 2>(2);
std::cout << v.value << std::endl;
return 0;
}
from here
If a static data member is of const integral or const enumeration type, you may specify a constant initializer in the static data member's declaration. This constant initializer must be an integral constant expression. Note that the constant initializer is not a definition. You still need to define the static member in an enclosing namespace.
In the cases that is working, the compilers are being non-compliant. Microsoft is non-compliant cuz Microsoft is almost never compliant, the g++ with -O2 is kinda funny, but in either case you've got no definition!
Edit:
As a rule of thumb, I always define my static constant member variables outside of the class because then I never have to remember it. In this case, class A would be invalid if T was anything other than an integral type, such as a float. So rather than do any patterns around the exception, I tend to just stick with my patterns around the rule.
I am trying to get the address of a static method from a class that is passed as a template argument to another class. Below is a pared down example:
#include <iostream>
#include <array>
using namespace std;
typedef size_t Data;
class MyFunction
{
private:
static const std::array<std::string, 3> values;
public:
template<size_t N>
static void Func(const Data& aData)
{
size_t index = (N > aData ? 2 : (N == aData ? 1 : 0) );
cout << "Function::Func<"<< N << ">:\t" << N << values[index] << aData << endl;
}
typedef decltype(&Func<0>) type;
};
const std::array<std::string, 3> MyFunction::values {"<", "=", ">"};
template<class Function, size_t N>
class FunctionManager
{
private:
static const typename Function::type func_;
static constexpr typename Function::type Create()
{
return &Function::Func<N>; //ERROR: Causes "overloaded function with no contextual information".
}
public:
void operator()(const Data &aData) const
{
func_(aData);
}
};
template<class Function, size_t N>
const typename Function::type FunctionManager<Function, N>::func_ = FunctionManager<Function, N>::Create();
int main()
{
static const size_t N = 6;
auto man = FunctionManager<MyFunction, N>();
man(N/2);
return 0;
}
You can also find the code here. The problem is in the Create() function, I get "address of overloaded function with no contextual type information" error. However, if I change &Function::Func to &MyFunction::Func, it works fine. I would like to make the actual function a template parameter and not hard-code it, anyone have any idea how to fix this problem? Note that I realize there are simpler ways of doing what I'm trying to do, but the actual code instead of a single Function::type creates an array of them using the index trick, etc. Any help would be greatly appreciated.
The error message causes some head scratching, indeed. Here's what's missing:
return &Function::template Func<N>;
// ^^^^^^^^
Function is a template parameter and you need to help the compiler and tell it that the nested name Func names a template.
I'm creating a trait class to help with my program. I have a template class called operations that contains the methods display and area. When I define these functions I get errors. Here they are:
error: specializing member ‘traits::operations<Rectangle>::display’ requires ‘template<>’ syntax
error: specializing member ‘traits::operations<Rectangle>::area’ requires ‘template<>’ syntax
As you can see, the compiler wants me to insert template <> just before those definitions. But when I do, I get a huge page of errors. What's going wrong and how can I fix it?
Here is my program.
namespace traits
{
template <typename P>
struct operations
{
static void display(Rectangle const &, std::ostream &);
static void area(Rectangle const &);
};
template <typename P, int N>
struct access {};
}
namespace traits
{
template <int N>
struct access<Rectangle, N>
{
static double get(Rectangle const &);
};
}
// The errors occur here
namespace traits
{
static void operations<Rectangle>::display(Rectangle const &rect, std::ostream &os)
{
os << rect.width << '\n';
os << rect.height << '\n';
os << area(rect) << '\n';
}
static void operations<Rectangle>::area(Rectangle const& rect)
{
double width = get<0>(rect);
double height = get<1>(rect);
return width * height;
}
}
namespace traits
{
template <>
struct access<Rectangle, 0>
{
static double get(Rectangle const &rect)
{
return rect.width;
}
};
template <>
struct access<Rectangle, 1>
{
static double get(Rectangle const &rect)
{
return rect.height;
}
};
}
template <int N, typename P>
static inline double get(P const &p)
{
return traits::access<P, N>::get(p);
}
template <typename P>
static inline void display(P const &p)
{
traits::operations<P>::display(p, std::cout);
}
template <typename P>
static inline double area(P const &p)
{
return traits::operations<P>::area(p);
}
int main()
{
}
Here is a program which shows the error - http://ideone.com/WFlnb2#view_edit_box
Any and all help is appreciated.
Thanks to help from the comments I got rid of those two errors, but I'm not getting more after adding the template<> declaration and fixing the return type of area:
error: cannot declare member function ‘static void traits::operations<P>::display(const Rectangle&, std::ostream&) [with P = Rectangle; std::ostream = std::basic_ostream<char>]’ to have static linkage [-fpermissive]
error: explicit template specialization cannot have a storage class
error: specialization of ‘static double traits::operations<P>::area(const Rectangle&) [with P = Rectangle]’ after instantiation
error: explicit template specialization cannot have a storage class
Your functions : display and area should be write like this:
template <>
double operations<Rectangle>::area( Rectangle const& rect )
{
double width = get<0>(rect);
double height = get<1>(rect);
return width * height;
}
As for template specialized functions, template <> should be placed
at the head of the function.
For static member functions, static should not appear at the
definition body of the function.
template< typename P > // P is declared here
struct operations {
... // into this scope
}; // but it goes out of scope here
template< typename P > // So it needs to be redeclared
void operations::display( Rectangle const &, std::ostream &) {
... // for this scope.
}
The function display doesn't "own" the names of its parameters. The template parameter must be redeclared in the definition. The compiler message is referring to template<> syntax to suggest you place something inside the <> brackets, but confusingly, leaving the brackets empty and literally saying template<> means something else — explicit specialization, which isn't what you want here.
On the other hand, static is a property of a member function which does not get mentioned in the definition. The compiler remembers static after using the other parts of the definition signature to match it to the declaration signature. So, you should erase static from the definition.