I want to try to do a generic getter by using C++11, but I have an issue if I try to define the generic getter outside the template class.
This code works fine
template <typename T>
class test
{
public:
........
//generic getter
template <typename F>
auto getter_elem_member(F fun)->decltype(fun())
{ return elem.fun(); }
private
T elem;
};
but if I try the code in this way:
template <typename T>
class test
{
public:
........
//generic getter
template <typename F>
auto getter_elem_member(F fun)->decltype(fun());
private
T elem;
};
template <typename T>
template <typename F>
auto test<T>::getter_elem_member(F fun)->decltype(fun())
{ return elem.fun(); }
I obtain the error "Member declaration not found".
Where am I wrong?
Thanks in advance for any suggestions
I am doing exercises with new features, here a example that works (unless a warning)
#include <iostream>
#include <string>
template <typename T>
class test
{
public:
//costruttori - distruttori
test(){}
~test(){}
public:
//generic getter
template <typename F>
auto getter_elem_member(F fun)
{ return (elem.*fun)(); }
//generic getter
template <typename F>
auto getter_elem_member2(F fun)->decltype(fun())
{ return fun(); }
private:
T elem;
};
struct A
{
std::string print(){return "ciao";}
static std::string print2(){return "ciao";}
};
int main()
{
test<A> test1;
std::cout << test1.getter_elem_member(&A::print) << std::endl;
std::cout << test1.getter_elem_member2(A::print2) << std::endl;
}
If you're trying to make a proxy function which calls a member function of a private member variable through a member function pointer, I don't think you need decltype at all.
// Member function pointer version
template <class Ret>
Ret getter_elem_member(Ret (T::*fun)())
{ return (elem.*fun)(); }
// Generic function object version
template <class F>
auto getter_elem_member(F fun) -> decltype(fun())
{ return fun(); }
If a function pointer is given, the first one will be called. For other callable types, the second one will be called.
The second one, which is for a generic callable object, seems unnecessary. Since you can't access the private member in fun anyway, so it's better calling fun() outside than passing it and making your class call it.
It appears that you're trying to use a template function-like paradigm.
You should use std::function to do this. If not, you can probably get along with some sort of templated function pointer to do this.
Related
I created a template called debug which is indirectly invoked through the function errorMsg. I then specialised the template to account for char * (code w/comments below hopefully helps with explanations)
After some playing around I was surprised that even though I defined the template specialisations at a point after they're called in errorMsg(), they were still being used.
I would have assumed because it had not yet been defined at the point the main template would instantiate a default copy or an error would occur
Any help resolving this issue would be great thanks
#include "header.h"
int main()
{
//std::vector<std::string> s_vec{"abc","cede","rfind"};
int i = 3;
int *j = &i;
errorMsg(std::cout,"hey"); //<---calls debug
}
//defined specialisations after its invoked inside errorMsg
template <>
inline std::string debug(char * p)
{
std::cout<<"specialsed char"<<std::endl;
return debug(std::string(p));
}
template <>
inline std::string debug(const char *p)
{
std::cout<<"specialised const char"<<std::endl;
return debug(std::string(p));
(header.h)
#include <iostream>
#include <sstream>
#include <string>
//(1)
template <typename T>
std::string debug(const T&s)
{
std::cout<<"unspecialised obj"<<std::endl;
std::ostringstream oss;
oss<<s;
return oss.str();
}
//(2)
template <typename T>
std::string debug(T *ptr)
{
std::cout<<"unspecialised raw ptr"<<std::endl;
std::ostringstream oss;
oss << "pointer: "<<ptr;
if (ptr)
{
oss<<" "<<debug(*ptr);
}
else
oss<<" null pointer";
return oss.str();
}
template <typename T, typename... Args> void print(std::ostream &os,const T &t,const Args&...rest);
template <typename T> std::ostream &print(std::ostream &os, const T &t);
template <typename... Args>
void errorMsg(std::ostream &os,Args &&...args)
{
print(os,debug(std::forward<Args>(args))...); //debug called here
}
template <typename T>
std::ostream &print(std::ostream &os, const T &t)
{
return os<<t<<std::endl;
}
template <typename T, typename... Args>
void print(std::ostream &os,const T &t,const Args&...rest)
{
os<<t<<", ";
print(os,rest...);
}
result:
specialised const char
unspecialised obj
hey
[temp.expl.spec]/6 If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
Your program is ill-formed; no diagnostic required.
I am trying to create class deriving from variadic template. Here is the code:
struct Some { };
template < class Base, class T >
struct Feature
{
protected:
void DoStuff(T& t) { }
};
template < class T, class ... Ts >
struct MultiFeature
: public Feature< T, Ts >...
{
};
class TestFeature
: public MultiFeature< Some, std::int16_t, std::string >
{
public:
void TestDoStuff()
{
std::int16_t i;
DoStuff(i);
}
};
Feature should be a simple wrapper around some basic type (in this case, integer and string), providing some functionality to class deriving from it. MultiFeature is used so that I do not have to derive from Feature< std::int16_t >, Feature< std::string >.
As far as I understand, there should be no ambiguity in this case, because there are two different DoStuff functions, each taking different parameter type, however VS2017 complains about ambiguous access. Is this correct behavior? If so, is there any simple workaround around this problem?
EDIT
It seems that compiler is right here, however in this answer, suggested workaround for this is to bring base class member functions into scope with using (Ambiguous access to base class template member function). Is it somehow possible to do this for variadic template base class?
It seems that compiler is right here, however in this answer, suggested workaround for this is to bring base class member functions into scope with using (Ambiguous access to base class template member function). Is it somehow possible to do this for variadic template base class?
If you can use C++17, it's trivially simple
template <typename T, typename ... Ts>
struct MultiFeature : public Feature<T, Ts>...
{
using Feature<T, Ts>::DoStuff...;
};
Unfortunately the variadic using is introduced in C++17 so, in C++11 and C++14, the best I can imagine is a MultiFeature recursive definition
// ground case: a fake DoStuff to abilitate following using
template <typename T, typename ... Ts>
struct MultiFeature
{ void DoStuff () { } };
// recursion case
template <typename T, typename T0, typename ... Ts>
struct MultiFeature<T, T0, Ts...>
: public Feature<T, T0>, public MultiFeature<T, Ts...>
{
using Feature<T, T0>::DoStuff;
using MultiFeature<T, Ts...>::DoStuff;
};
The following is a full compiling example (with both cases)
struct Some { };
template <typename, typename T>
struct Feature
{
protected:
void DoStuff (T &) { }
};
#if 0
template <typename T, typename ... Ts>
struct MultiFeature : public Feature<T, Ts>...
{
using Feature<T, Ts>::DoStuff...;
};
#else
// ground case: a fake DoStuff to abilitate following using
template <typename T, typename ... Ts>
struct MultiFeature
{ void DoStuff () { } };
// recursion case
template <typename T, typename T0, typename ... Ts>
struct MultiFeature<T, T0, Ts...>
: public Feature<T, T0>, public MultiFeature<T, Ts...>
{
using Feature<T, T0>::DoStuff;
using MultiFeature<T, Ts...>::DoStuff;
};
#endif
struct TestFeature
: public MultiFeature<Some, short, int, long, long long>
{
void TestDoStuff ()
{ int a{}; DoStuff(a); }
};
int main ()
{
TestFeature tf;
}
I have a C++11 template that can be specialized with an arbitrary type parameter.
template<class ElementType>
class Foo
How do I declare a constructor that appears for the compiler's consideration only when ElementType is e.g. const uint8_t?
That is, I have a bunch of constructors that are generic over any ElementType, but I also want to have constructors that are only considered when ElementType is specialized in a particular way. (Allowing those constructors to be selected for other types would be unsafe.)
So far std::enable_if examples that I've found have been conditional on the types of the arguments of the constructors.
template<class ElementType>
struct Foo
{
template <typename T = ElementType>
Foo(typename std::enable_if<!std::is_same<T, const uint8_t>{}>::type* = nullptr) {}
template <typename T = ElementType>
Foo(typename std::enable_if<std::is_same<T, const uint8_t>{}>::type* = nullptr) {}
};
int main()
{
Foo<int> a{}; // ok, calls first constructor
Foo<const uint8_t> b{}; // ok, calls second constructor
}
wandbox example
You can break the class into two classes. The derived class' purpose is to be able to specialize constructors for different types. E.g.:
#include <cstdio>
#include <cstdint>
template<class ElementType>
struct Foo_
{
Foo_() { std::printf("%s\n", __PRETTY_FUNCTION__); }
};
template<class ElementType>
struct Foo : Foo_<ElementType>
{
using Foo_<ElementType>::Foo_; // Generic version.
};
template<>
struct Foo<uint8_t> : Foo_<uint8_t>
{
Foo() { std::printf("%s\n", __PRETTY_FUNCTION__); } // Specialization for uint8_t.
};
int main(int ac, char**) {
Foo<int8_t> a;
Foo<uint8_t> b;
}
The benefit of using the derived class here compared to enable_if is that:
The class can be partially specialized.
Only one specialization of the class is chosen for particular template parameters, rather than a set of constructors. When adding specializations for new types the existing enable_if expressions may need to be changed to make them more restrictive to avoid function overload set resolution ambiguity.
The following is a mockup code that I wrote to experiment with trailing return types in a CRTP setup.
#include <iostream>
#include <memory>
#include <utility>
using namespace std;
struct t_aspect{
struct t_param1 {};
};
// Generic Selector
template <typename t_detail>
struct Select;
template <>
struct Select<t_aspect::t_param1> {
using typeof = t_aspect::t_param1;
};
//Base CRTP class
template<typename dclas>
class CrtpB
{
public:
template<typename T1>
auto func1() -> // What should be here?
{
return(static_cast<dclas*>(this)->func1<T1>());
}
};
//Derived CRTP class
class CrtpD : public CrtpB<CrtpD>
{
private:
uint32_t param1 = 0;
private:
auto func1(const t_aspect::t_param1&) -> uint32_t
{
return(param1);
}
public:
static auto create() -> unique_ptr<CrtpB>
{
return(unique_ptr<CrtpD>(new CrtpD));
}
template<typename T1>
auto func1() -> decltype(func1(typename Select<T1>::typeof()))
{
return(func1(typename Select<T1>::typeof()));
}
};
int main()
{
auto crtp = CrtpD::create();
auto parm = crtp->func1<t_aspect::t_param1>();
return 0;
}
I would like some help in deciphering what should be the trailing return type of func1 in CrtpB.
I have tried using
decltype(static_cast<dclas*>(this)->func1<T1>())
but this does not work. I have also tried writing a helper function based on a solution found in Inferring return type of templated member functions in CRTP.
template <typename D, typename T>
struct Helpr {
typedef decltype(static_cast<D*>(0)->func1<T>()) type;
};
But this does not work either.
dclas is an incomplete type when the base class is instantiated. You need to do two things to make this work:
Defer the checking of the type of func1<T1>() until the type is complete
Use the template keyword on the dependent expression so that the template definition is parsed correctly:
We can do this by adding a layer of indirection:
namespace detail {
template <class T, class Func1Arg>
struct func1_t {
using type = decltype(std::declval<T>().template func1<Func1Arg>());
};
};
Then you use this trait as the trailing return type:
template<typename T1>
auto func1() -> typename detail::func1_t<dclas,T1>::type
{
return(static_cast<dclas*>(this)->template func1<T1>());
}
I am writing a library that I would like to keep header-only. In the code I have something like this:
// Wrapper.h
#ifndef INCLUDED_WRAPPER_H
#define INCLUDED_WRAPPER_H
namespace quux {
template <typename T, typename U>
class Wrapper
{
T m_t;
U m_u;
public:
Wrapper(T const & t, U const & u) : m_t(t), m_u(u) { }
// ...
};
} // namespace quux
#endif // INCLUDED_WRAPPER_H
// Foo.h
#ifndef INCLUDED_FOO_H
#define INCLUDED_FOO_H
#include <type_traits>
#include "Wrapper.h"
namespace quux {
// if some type is special, then there will be a specialization of this
// struct derived from std::true_type
template <typename T> struct is_special : std::false_type { };
class Foo
{
template <typename T>
Wrapper<Foo, T> impl(T const & t, std::true_type ) const
{
return Wrapper<Foo, T>(*this, t);
}
template <typename T>
T const & impl(T const & t, std::false_type ) const;
{
return t;
}
public:
template <typename T>
auto operator()(T const & t) const // using automatic return type deduction
{
return impl(t, is_special<T>());
}
};
#if 1
Foo const foo;
#else
template <typename T>
auto foo(T const & t) // using automatic return type deduction
{
return Foo()(t);
}
#endif
} // namespace quux
#endif // INCLUDED_FOO_H
I see two different ways to have a callable entity with the name "quux::foo": a constant object named foo (the #if 1 - branch) or a function named foo that forwards its arguments to a Foo-object (the #else-branch). Which version should I prefer? A const Object has internal linkage so there are no linker errors if the header is included in multiple translation units. Are there any salient differences between the two approaches?
As you are calling a function, and your function object has no state, I would go with the function interface.
First, because functions can be overloaded, while function objects cannot outside of the body of the function object. You may wish to enable ADL extensions to your function.
Second because function objects are wierd. They cannot be converted to function pointers (in your case for no good reason), for example (note you can fix that with more boilerplate). Weird solutions are only a good idea when simple solutions are insufficient: in this case the simple perfect forwarding function is simpler.
Finally you might want to make your functions perfect forward, and have T&& rvalues give functions that return T at the outermost API level. This enables lifetime extension of temporaries to pass through your functions.