The concept of variadic templates is quite confusing to me and I want to make it a bit more complex (well I think...).
Let us consider the following code:
template <typename T>
class base
{
template <typename... E>
virtual void variadic_method_here(E... args) = 0;
};
and an implementing class:
class derive : public base<some_object>
{
void variadic_method_here(concrete_args_here);
};
How do I do that?
I think if I were faced with this problem I'd use CRTP and overloads to solve the problem.
e.g.:
#include <iostream>
template <typename Impl>
class base {
public:
template <typename... E>
void foo(E... args) {
Impl::foo_real(args...);
}
};
class derived : public base<derived> {
public:
static void foo_real(double, double) {
std::cout << "Two doubles" << std::endl;
}
static void foo_real(char) {
std::cout << "Char" << std::endl;
}
};
int main() {
derived bar;
bar.foo(1.0,1.0);
bar.foo('h');
}
You can't have a templated virtual function.
Related
I want to write an Adapter for two different classes ClassA and ClassB - neither are mine and both have template member functions. I want to use Adapter as argument of a pure virtual member function of a class Base in order to avoid overloading of Base::do_something for ClassA and ClassB since a lot of classes will inherit from Base.
The code below is based on static polymorphism and shows how far I have got. However, extending the Adapter to work with a third class, say ClassC, always requires to change Adapter.
I wonder if there is a better way out there to write such an adapter which also can be easily extended (like in the classical adapter pattern). It would be great if someone could give me a good hint.
#include <iostream>
#include <typeinfo>
#include <variant>
template<class ...Ts>
struct overloaded : Ts...
{
overloaded(const Ts&... args) : Ts(args)... { }
using Ts::operator()...;
};
struct ClassA
{
template <class T>
std::string get_type() const {return typeid(T()).name();}
};
struct ClassB
{
template <class T>
void old_print_type() const {std::cout << typeid(T()).name();}
};
struct Adapter
{
template <class Adaptee>
Adapter (Adaptee* a) : adaptee(a) {};
template <class T>
void print_type() const
{
std::visit(overloaded(
[](ClassA* v){ std::cout << v->get_type<T>();},
[](ClassB* v){ v->old_print_type<T>();}
),adaptee);
}
using adaptee_type = std::variant<ClassA*,ClassB*>;
adaptee_type adaptee;
};
struct Base
{
virtual void do_something(const Adapter&) = 0;
virtual ~Base() = default;
};
int main()
{
ClassA a;
ClassB b;
Adapter adapterA(&a);
Adapter adapterB(&b);
adapterA.print_type<double>();
std::cout << std::endl;
adapterB.print_type<double>();
}
I need to determine at compile time if an abstract class T (passed in as a template parameter) has a protected or private parameterless constructor. Because T is abstract, all the versions of the std::is_constructible<T> family return false no matter what.
I've tried defining a class U that inherits from the class in question, has using T::T, and is concrete; unfortunately, I've found the using directive ignores the default constructor;
(I need this for SFINAE purposes; I need to make my templated concrete-version-of-T factory refuse to work for T with explicitly inaccessible constructors.)
This is what I'm trying to make happen:
#include <iostream>
#include <utility>
template <typename T, typename... Args>
static T* make(Args&&...);
class Base {
public:
void ImportantFunctionThatRequiresFactorySupport();
private:
class InstantiationToken {};
virtual InstantiationToken* NoInstantiationForYou() = 0;
template <typename T>
class Deabstractifier final : public T {
private:
InstantiationToken* NoInstantiationForYou() { return NULL; }
};
template <typename T, typename... Args>
friend T* make(Args&&...);
};
template <typename T, typename... Args>
static T* make(Args&&... args) {
// There should be a static_assert here to detect when T has a protected constructor and refuse to make one
return new Base::Deabstractifier<T>(std::forward<Args>(args)...);
}
class IntermediateDerivedThatIsFineToConstruct : public Base {
public:
IntermediateDerivedThatIsFineToConstruct() = default;
void DoSomethingOrdinaryAndCompletelyReasonable() {
ImportantFunctionThatRequiresFactorySupport();
}
};
class IntermediateDerivedThatShouldOnlyBeInheritedFrom : public Base {
protected:
IntermediateDerivedThatShouldOnlyBeInheritedFrom() = default;
public:
void SomethingElseCompletelyReasonable() {
ImportantFunctionThatRequiresFactorySupport();
}
};
class ThingThatShouldBeConstructibleAgain : public IntermediateDerivedThatShouldOnlyBeInheritedFrom {
public:
void SomeExtaFunctionality() {};
};
int main()
{
std::cout << "Starting..." << std::endl;
make<IntermediateDerivedThatIsFineToConstruct>(); // Should succeed
std::cout << "Did thing 1" << std::endl;
make<ThingThatShouldBeConstructibleAgain>(); // Should succeed
std::cout << "Did thing 2" << std::endl;
make<IntermediateDerivedThatShouldOnlyBeInheritedFrom>(); // Should fail at compile time
std::cout << "Did thing 3" << std::endl;
}
live on coliru
Is it possible to create a class template with a member function definition only if the object created is of a specific type?
I've created a template class I will use for storing either int or doubles, but for doubles I would like to be able to set precision too (objects created with myclass < double> should have this functionality, but for myclass< int> there is no need for that to be present at all).
I know I can use a base class template, and create new classes "myInt", "myDouble" using that and implement the functionality only in the myDouble class, but I think it would be cleaner to define the functionality (both the function and a member variable) for doubles in the class template, if that's possible and preferable?
Let's add an example to show what I want to do:
#include <iostream>
#include <iomanip>
class commonBase{
public:
void setState(int state);
virtual void print() = 0;
private:
int _my_state;
};
template <typename T>
class generalObject : public commonBase {
public:
void value(T value);
void print(){ std::cout << "My value: " << _my_value << std::endl; }
private:
T _my_value;
};
template <typename T>
void generalObject<T>::value(T value){
_my_value = value;
}
// Is there any way do specialize only only whats different from the generalObject template?
// Here I thought I could specialize the case where a generalObject is created of <double>, but
// when I do, nothing is derived from generalObject (or at least not visible as far as I can tell)
template<>
class generalObject<double>{
public:
void setPrecision(int precision){ _my_precision = precision; }
// here I would like a special implementation of print(), which overrides the print() in generalObject
// and instead also prints according to the precision set when the object is of <double> type.
// Row below an example which doesn't work (compiler error, _my_value undefined)
void print(){ std::cout << "My value: " << std::setprecision(_my_precision) << _my_value << std::endl; }
private:
int _my_precision;
};
int main(int argc, char* argv[]){
generalObject<int> o1;
o1.value(1);
o1.print();
o1.setState(1); //inherited from the commonBase
generalObject<double> o2;
o2.setPrecision(2);
o2.value(2); //here value isn't available (compile error)
o2.print();
o2.setState(123); //also isn't available (compile error)
}
Sure.
template <typename T> class Poly;
void set_precision(Poly<double>* self, int a) {};
If you really want dot notation you can then add:
template <typename T> class Poly {
public: void set_precision(int a){::set_precision(this,a);}
...
However I think you should think about what you're trying to accomplish. If MyInt and MyDouble have different fields and different methods and different implementations, they should probably be different classes.
This can be solved using template specialization.
We first define a common template...
template< typename T >
struct myclass
{
// common stuff
};
... and specialize that for double:
template<>
struct myclass<double>
{
int precision = 10;
void setprecision( int p ){ precision = p; }
};
Now the setprecision() method can only be called for myclass<double>. The compiler will complain if we try to call it for anything else, like myclass<int>.
int main()
{
myclass<double> d;
d.setprecision( 42 ); // compiles
myclass<int> i;
i.setprecision( 42 ); // fails to compile, as expected
}
Demo.
The basic way to have a member function of a class template exist only for some template parameters is to create a specialization of the class template for those template parameters.
template<typename T>class X{
// general definition
};
template<>class X<double>{
// double-specific definition
};
The downside of this is that the specialization will need to duplicate anything that is common. One way to address this is to move the common things out to a base class template:
template<typename T>class Xcommon{
// common stuff
};
template<typename T>class X: public Xcommon<T>{
// general definition
};
template<>class X<double>: public Xcommon<double>{
// double-specific definition
};
Alternatively, you can do it the other way: put the common stuff in the derived class, and the extras in the base, and specialize the base:
template<typename T>class Xextras{
// empty by default
};
template<typename T>class X: public Xextras<T>{
// common definition
};
template<>class Xextras<double>{
// double-specific definition
};
Either way can work; which is better depends on the details.
Both these methods work for data members and member functions.
Alternatively, you can use enable_if to mean that member functions are not selected by overload resolution if the template parameter doesn't meet a required condition. This requires that the member function is itself a template.
template<typename T>class X{
template<typename U=T> // make it a template,
std::enable_if<std::is_same_v<U,double>> double_specific_function(){
// do stuff
}
};
I wouldn't recommend this option unless there is no other choice.
If the question is about a member function, then here is one of the ways to do it without class template specialization:
#include <iostream>
#include <type_traits>
template <typename T>
struct Type {
template <typename U = T,
typename = typename std::enable_if<std::is_same<U, double>::value>::type>
void only_for_double() {
std::cout << "a doubling" << std::endl;
}
};
int main() {
Type<int> n;
Type<double> d;
// n.only_for_double(); // does not compile.
d.only_for_double();
}
Example on ideone.com
If you require a data-member presence based on the template parameter, you will have to do some kind of specialization, in which case it is, probably, simpler to put the function into corresponding specialization.
EDIT: After OP made his question more specific
Here is one way to do it without extra class and getting rid of virtual functions. Hope it helps.
#include <iostream>
#include <iomanip>
template <typename T, typename Derived = void>
class commonBase {
public:
void setState(int state) {
_my_state = state;
}
void value(T value) {
_my_value = value;
}
template <typename U = Derived,
typename std::enable_if<std::is_same<U, void>::value,
void * >::type = nullptr>
void print() const {
std::cout << "My value: " << _my_value << std::endl;
}
template <typename U = Derived,
typename std::enable_if<!std::is_same<U, void>::value,
void * >::type = nullptr>
void print() const {
static_cast<Derived const *>(this)->_print();
}
protected:
T _my_value;
int _my_state;
};
template <typename T>
class generalObject : public commonBase<T> {
};
template<>
class generalObject<double> : public commonBase<double, generalObject<double>> {
private:
friend commonBase<double, generalObject<double>>;
void _print() const {
std::cout << "My value: " << std::setprecision(_my_precision) <<
_my_value << std::endl;
}
public:
void setPrecision(int precision){ _my_precision = precision; }
private:
int _my_precision;
};
int main(){
generalObject<int> o1;
o1.value(1);
o1.print();
o1.setState(1);
generalObject<double> o2;
o2.setPrecision(2);
o2.value(1.234);
o2.print();
o2.setState(123);
}
Same code on ideone.com
I know partial template specialization isn't supported for functions and class methods, so my question is: What are common solutions or patterns to resolve this? Below Derived derives from Base, and both of these classes have virtual methods greet() and speak(). Foo's holds a std::array<unique_ptr<T>, N> and is used in do_something(). Foo has two template parameters: T (the class type) and N (number of elements of the std::array) If N = 2, there exists a highly optimized version of do_something(). Now assume that Foo's T parameter isn't always the base class Base. Ideally, I would like to write the following code, but it's illegal:
//ILLEGAL
template<typename T>
void Foo<T,2>::do_something()
{
arr_[0]->greet();
}
Below is the full code and my current (ugly) solution. I have to specialize do_something() twice, once for Base and once for Derived. This gets ugly if there exists multiple methods like do_something() that can be optimized on the special N=2 case, and if there exists many subclasses of Base.
#include <iostream>
#include <memory>
class Base
{
public:
virtual void speak()
{
std::cout << "base is speaking" << std::endl;
}
virtual void greet()
{
std::cout << "base is greeting" << std::endl;
}
};
class Derived : public Base
{
public:
void speak()
{
std::cout << "derived is speaking" << std::endl;
}
void greet()
{
std::cout << "derived is greeting" << std::endl;
}
};
template<typename T, int N>
class Foo
{
public:
Foo(std::array<std::unique_ptr<T>, N>&& arr) :
arr_(std::move(arr))
{
}
void do_something();
std::array<std::unique_ptr<T>, N> arr_;
};
template<typename T, int N>
void Foo<T,N>::do_something()
{
arr_[0]->speak();
}
//Want to avoid "copy-and_paste" of do_something() below
template<>
void Foo<Base,2>::do_something()
{
arr_[0]->greet();
}
template<>
void Foo<Derived,2>::do_something()
{
arr_[0]->greet();
}
int main()
{
constexpr int N = 2;
std::array<std::unique_ptr<Derived>, N> arr =
{
std::unique_ptr<Derived>(new Derived),
std::unique_ptr<Derived>(new Derived)
};
Foo<Derived, N> foo(std::move(arr));
foo.do_something();
return 0;
}
The trick is to forward implementation to an helper template class, and partial specialize that class and/or use tag dispatching:
namespace {
template<typename T, int N, bool isBase = std::is_base_of<Base, T>::value>
struct helper {
// general case:
void operator () (std::array<std::unique_ptr<T>, N>& arr_) const
{
arr_[0]->speak();
}
};
template<typename T>
struct helper<T, 2, true>
{
void operator () (std::array<std::unique_ptr<T>, 2>& arr_) const
{
arr_[0]->greet();
}
};
// You may add other specialization if required.
}
template<typename T, int N>
void Foo<T,N>::do_something()
{
helper<T, N>()(arr_);
}
There are different alternatives, depending on how other constrains in the problem one might be more appropriate than another.
The first one is to forward the request to a static function in a template class, which allows for partial specializations:
template <int N>
struct Helper {
template <typename T>
static void talk(T& t) { // Should be T const &, but that requires const members
t.speak();
}
};
template <>
struct Helper<2> {
template <typename T>
static void talk(T& t) {
t.greet();
}
}
;
Then the implementation of do_something would be:
template <typename T, int N>
void Foo<T,N>::do_something() {
Helper<N>::talk(*arr_[0]);
}
Alternatively, you can use tag dispatch to select one of multiple overloads:
template <int N> struct tag {};
template <typename T, int N>
template <int M>
void Foo<T,N>::do_something_impl(tag<M>) {
arr_[0]->speak();
}
template <typename T, int N>
void Foo<T,N>::do_something_impl(tag<2>) {
arr_[0]->greet();
}
template <typename T, int N>
void Foo<T,N>::do_something() {
do_something_impl(tag<N>());
}
Where I have created a tag-type that can be specialized for any possible N. You could also use existing tools in C++11.
Finally, if you need to do something like this for different functions, you can use inheritance, and push some of the functionality to a base that resolves the differences. This can be done by either pushing common code to a base, differences to an intermediate level and using a lower level front type that just inherits from the rest (base contains generic code, derived types specialize). Or alternatively with CRTP (base(s) contain differences, derived type generic code and pulls specific implementations from the bases.
Why won't the compiler select the Interface template when running the following code? Are additional declarations / hints needed or won't this work in general?
I'm just curious if this is actually possible.
class Interface {
public :
virtual void Method() = 0;
virtual ~Interface() { }
};
class Derived : Interface {
public :
void Method() {
cout<<"Interface method"<<endl;
}
};
template<typename T>
struct Selector {
static void Select(T& o) {
cout<<"Generic method"<<endl;
}
};
template<>
struct Selector<Interface> {
static void Select(Interface& o) {
o.Method();
}
};
int i;
Selector<int>::Select(i) // prints out "Generic method" -> ok
Derived d;
Selector<Derived>::Select(d); // prints out "Generic method" -> wrong
// should be "Interface method"
Try this (and #include <type_traits>):
template <typename T, typename = void>
struct Selector
{
static void Select(T & o)
{
std::cout << "Generic method" << std::endl;
}
};
template <typename T>
struct Selector<T,
typename std::enable_if<std::is_base_of<Interface, T>::value>::type>
{
static void Select(Interface & o)
{
o.Method();
}
};
It turns out that enable_if combined with defaulted template arguments can be used to guide partial specialisations.
The compiler will select the version of a function that is the closest match. A function that takes the exact type for a parameter always wins over one that requires a conversion. In this case the template function is an exact match, since it matches anything; the Interface specialization would require the conversion of the parameter from a Derived to an Interface.
This will allow you to achieve the desired result:
#include <iostream>
#include <type_traits>
using namespace std;
class Interface {
public :
virtual void Method() = 0;
virtual ~Interface() { }
};
class Derived : public Interface {
public :
void Method() {
cout<<"Interface method"<<endl;
}
};
template<typename T, typename S = void>
struct Selector {
static void Select(T& o) {
cout<<"Generic method"<<endl;
}
};
template<typename T>
struct Selector<T, typename enable_if< is_base_of<Interface, T>::value >::type> {
static void Select(Interface& o) {
o.Method();
}
};
int main()
{
int i;
Selector<int>::Select(i); // prints out "Generic method" -> ok
Derived d;
Selector<Derived>::Select(d); // prints out "Generic method" -> wrong
// should be "Interface method"
}