I am trying to specialize a template this way:
class PropertyBase
{
public:
SfPropertyBase(string name)
{
Name = name;
}
virtual ~SfPropertyBase() {}
string Name;
virtual bool FromString(Object* obj, string str) = 0;
};
template< typename T>
class Property : public SfPropertyBase
{
public:
Property(string name) : SfPropertyBase(name)
{
//specific to Property stuff
}
template<typename U = T>
typename std::enable_if<(std::is_class<U>::value && std::is_pointer<U>::value), bool>::type
FromString(Object* obj, string str)
{
//do something
return true;
}
template<typename U = T>
typename std::enable_if<!std::is_class<U>::value || !std::is_pointer<U>::value), bool>::type
FromString(Object* obj, string str)
{
//do something
return true;
}
}
Then, when I try to initialize an instance of this class:
auto prop = new Property<int>("IntProperty");
I get invalid new-expression of abstract class type Property<int>. I understand that there is an abstract function in PropertyBase, but I also provide both specializations for Property, where T is a class and where it isn't.
What is going on and how to fix it?
Note: what I want to achieve is to specialize FromString if T is a class/pointer and all the other cases.
Both the FromString in Property are function template, they can't override the non-template virtual function of the base class. (In fact functions templates cannot be virtual functions).
You could add another non-template FromString in Property; and you can ensure the overriding by using the keyword orverride. e.g.
bool FromString(Object* obj, string str) override {
return FromString<>(obj, str);
}
LIVE
A function template cannot be used as an overrider for a non-template virtual function. A function template is not a function, it's a recipe for creating functions on demand when a call is made.
Code will have to call FromString on your derived class object directly for SFINAE to work. If you want to provide a different overrider based on the template parameter type, one approach is to go via an intermediate base.
template<typename T, typename = void>
struct FromStringProvider;
template<typename T>
struct FromStringProvider<T, typename std::enable_if<(std::is_class<U>::value && std::is_pointer<U>::value)>::type> : SfPropertyBase {
bool FromString(Object* obj, string str) override
{
//do something
return true;
}
};
If you need access to the deriving class, then a CRTP based approach can be used. Just pass the deriving class as an extra parameter and rely on its static interface to access the parts you need.
This alternative approach is especially useful if you have sets of virtual functions, all under the same conditions.
Related
I was wondering if there was any way to do something like this in C++:
$(some typename) func() {
if (/*condition*/) return int;
else return bool;
}
Edit: I think I wasn't clear enough. I was wondering if you could say something like this: func() var = /*something*/. Basically, the function is returning something like int or bool (the type, not a value of that type).
A function cannot choose which type to return at runtime; it must have a definite return type at compile time. What you can use instead is a template with a member type. You will need to use template metaprogramming for this. As an example, here is an adapter template that makes a type T into its const pointer form:
template <typename T>
struct make_const_ptr {
using type = const T*;
};
template <typename>
using make_const_ptr_t<T> = typename make_const_ptr<T>::type
This is essentially a "function" that returns a type, in the sense that you can "call" it by writing make_const_ptr_t<T>. You can do a bunch more operations on types using template metaprogramming: https://www.geeksforgeeks.org/template-metaprogramming-in-c/ .
Plus, you said in your comments that you wanted to use this to choose which template function to use on a polymorphic type. An even better way to do this is to use a virtual function; doing different things for different polymorphic types is the whole point of virtual functions:
template <typename T>
void template_function(const T& obj) {
// ...
}
class Base {
// ...
virtual void do_template_function() = 0;
};
class D : public Base {
virtual void do_template_function() {
template_function<D>(*this);
}
};
class E : public Base {
virtual void do_template_function() {
template_function<E>(*this);
}
};
void f(Base* obj) {
// ...
obj->do_template_function();
// ...
}
There is a cute library Boost.Hana that can be used for computations on types in C++ metaprogramming.
With Boost.Hana a function returning an object representing the C++ type could look like this:
auto func()
{
return hana::if_(
/*constexpr condition*/,
hana::type_c<int>,
hana::type_c<bool>
);
}
template<bool, class T, class U>
struct IF_ELSE { using type = T; };
template<class T, class U>
struct IF_ELSE<false, T, Y> { using type = U; }
template<class T>
class Object {
Object baz(IF_ELSE<boolean_condition<T>::value, foo_class, bar_class>::type param) {
return Object(param);
}
};
Hello I am trying to create a method that returns an object that is initialized based upon some template conditional. The code above works fine however I would like to use a default constructor (no parameters)
template<class T>
class Object {
Object baz(IF_ELSE<boolean_condition<T>::value, foo_class, void>::type param) {
return Object(param);
}
};
However it is not possible to use void as a type (despite void foo(void); being a valid decleration)
Is there anyway to do this?
Notes. I DO NOT WANT TO USE TEMPLATE SPECIALIZATION. Although this is a solution for this specific question it would be inconvenient simply use specialization in my current project. Personally I prefer the usage of IF_ELSE opposed to specialization as I find it much more comprehensible.
The only workaround I can think of is something like...
template<class T>
class Object {
Object baz(IF_ELSE<boolean_condition<T>::value, foo_class, int>::type param = 0) {
if (param == 0)
return Object();
else
return Object(param);
}
};
If anyone has a more sophisticated solution that would be great. Much thanks.
----------------------------------EDITED------------------------------
This workaround is a bit nicer (inspired by Oisyn) it more or less combines the best of both worlds of parameter specialization and default parameters. Possibly a bit faster too as it dodges the if statement.
template<class T>
class Object
{
public:
struct MAKE_ILLEGAL {};
template<class param>
Object(param p) {/*do stuff */}
Object() {/* default */ }
template<bool b>
Object<T> baz(std::conditional_t<b, int, MAKE_ILLEGAL> param)
{ return Object<T>(param); }
template<bool b>
Object<T> baz(std::conditional_t<b, MAKE_ILLEGAL, int> value = 0)
{ return Object<T>(); }
};
int main() {
Object<double> obj;
obj.baz<false>();
}
EDIT Apparently you're not allowed to use something that resolves to void as a function argument in a type-dependent context. I've edited my answer accordingly using a different solution. The original answer can be read below.
// A helper that always yields true so we can make the condition type-dependent
// on arbitrary template parameters
template<class T>
constexpr bool true_v = true;
template<class T>
class Object
{
public:
template<class U = void, std::enable_if_t<Condition<T>::value && true_v<U>, int> = 0>
Object baz(foo_class param)
{ return Object(param); }
template<class U = void, std::enable_if_t<!Condition<T>::value && true_v<U>, int> = 0>
Object baz()
{ return Object(); }
};
As long as we're not dealing with special methods like copy/move ctors and copy/move assignment operators (which may not be templatized), we can always apply regular SFINAE tricks. We just need to templatize baz using default template arguments, and make sure the condition used for std::enable_if is type-dependent on a template parameter of that method (and not solely on T in Object<T>)
Live version
Original answer
template<class T>
class Object
{
private:
struct dummy { };
public:
Object baz(std::conditional_t<Conditional<T>::value, foo_class, dummy> param)
{ return Object(param); }
Object baz(std::conditional_t<Conditional<T>::value, dummy, void>)
{ return Object(); }
};
The idea is that you create both overloads, one for a single parameter and one for none. By selectively replacing the parameter with an inaccessible dummy type, you can make sure you will never be able to call that overload when not appropriate.
Not sure if this question has been asked before. I am implementing a factory class. Every instance should inherit from a base class InstBase and should be initialized through a centralized factory.
class InstBase {
friend class Factory;
private:
InstBase() = default;
factory* factory;
}
class Factory {
template <typename Derived, typename... ArgsT>
InstBase* get(ArgsT&&... args) {
return new Derived(std::forward<ArgsT>(args)...)
}
}
class MyInst : public InstBase {
public:
MyInst(int a, int b) {...};
}
factory.get<MyInst>(1, 2);
As you can see in this example, the interface takes a Derived as a template and initialize an instance with user-defined argument list passed to the constructor of Derived. However, what I want to add here is assigning the pointer to the factory in which the instance is created. This can be done by:
template <typename Derived, typename... ArgsT>
InstBase* get(ArgsT&&... args) {
auto ptr = new Derived(std::forward<ArgsT>(args)...);
ptr->factory = this;
return ptr;
}
I felt this is a bit redundant because the base class InstBase is always created before the derived and can be only newed by the factory class. Is there any trick to achieve this goal without changing the interface of get? It doesn't make sense for me to ask user to attach another pointer to factory in the argument list (e.g., factory.get<MyInst>(1, 2, &factory)).
If you want to forbid the use of Factory as a type for the arguments, you can use something like this (C++11 compliant):
template<typename>
constexpr bool isBaseOf() { return false; }
template<typename T, typename U, typename... O>
constexpr bool isBaseOf() { return std::is_base_of<T, typename std::decay<U>::type>::value || isBaseOf<T, O...>(); }
Thus changing the factory method as it follows:
template <typename Derived, typename... ArgsT>
InstBase* get(ArgsT&&... args) {
static_assert(not isBaseOf<Factory, ArgsT...>(), "!");
return new Derived(std::forward<ArgsT>(args)...)
}
That said, I don't like it too much, for I won't use a class that does not let me use the parameters I want!!
I am trying to understand the concept of type traits.
Say i have some templatized Class Hierachy like this and a client function:
template<typename T>
class Base
{
public:
//...
virtual bool inline isSymmetric() const = 0;
};
template<typename T>
class ChildrenOperation : public Base<T>
{
public:
//...
virtual bool inline isSymmetric() const override
{
return true;
}
};
template<typename T>
void clientFunction(const Base<T>& operation)
{
//...
if(operation.isSymmetric())
{
// use operation in one way
} else {
// use operation in another way
}
}
Obviously, clientFunction is polymorphic and different children can have different implementations of isSymmetric.
However, since isSymmetric seems to be constant and really more of a type information, i've read about type traits and i was wondering whether it is possible to rewrite the client function to not depend on isSymmetric on runtime, but rather compile time.
I've tried adding a trait like this. But i am not sure how to specialize it and use it in a polymorphic context.
template <typename T>
struct is_symmetric {
static const bool value = false;
};
If being symmetric depends on the concrete type derived from Base, then you cannot use a type traits for this situation. Type traits are evaluated in compile time, so if you have a polymorphic type which's traits are not known at compile time, then you cannot use type traits.
One possible solution, if the symmetricity is really constant, is this:
class Base {
public:
Base(bool symmetric) : symmetric(symmetric) {}
bool isSymmetric() {
return symmetric;
}
// ...
private:
bool symmetric;
};
class ChildrenOperation : public Base {
public:
ChildrenOperation() : Base(true) {}
// ...
};
I did not use the templates here because they are irrelevant in this case. Of course, if symmetricity depends on T then you can use type traits, like this:
template <typename T>
struct is_symmetric : public std::false_type {};
template <>
struct is_symmetric<SymmetricT> : public std::true_type {};
So the solution depends on whether the trait depends only on the dynamic type of the object, in which case you should use the fist code, the template parameter, in which case you should use the second code, or both. From your example, it's not entirely clear which is your situation.
So I have run into a problem in which I need a method to be defined for any types that inherit from a base class that I have created, yet I need that method to be static, is there anyway I can force it to be created?
The reason I need this I will have people be extending my base class, but I need to be able to guarantee a call to a function like so derivedType derivedType::createFromSerialized(std::string) will work to create a new instance from a serialization.
Edit: I am trying to follow Richard J. Ross III's advice and use static_assert however I am running into some problems with that and I have a feeling its due to it being called from a templated class but I can't figure out how to fix it.
template <typename indType> class population {
static_assert(std::is_function<indType::createFromSerialized>::value, "message");
....
};
However that is giving me an error of to refer to a type member of a template parameter, use ‘typename indType:: createFromSerialized’ and no type named 'createFromSerialized' in 'class test'
The reason I am trying to use static_assert is to get a nicer error message that will give information about the proper function signature for createFromSerialized instead of just one that says its not defined.
This can be done by combining static_assert and SFINAE detection technique.
template<typename T, typename V = bool>
struct has_deserialize : std::false_type { };
template<typename T>
struct has_deserialize<T,
typename std::enable_if<
std::is_same<decltype(&T::createFromSerialized),
T* (*)(const std::string&)>::value,
bool
>::type
> : std::true_type { };
template <typename T>
class test
{
static_assert(has_deserialize<T>::value, "No suitable createFromSerialized");
};
What you are trying to accomplish is possible through a factory pattern very easily. Not sure whether you can accomplish it using templates.
Here's a skeleton of how I would go about implementing the serialization functionality.
SerializationFunctor.h
class Base;
class SerializationFunctor
{
virtual Base* operator(FILE* in) const = 0;
};
Base.h
class Base
{
bool registerSerializationFunction(std::string const& identifier,
SerializationFunctor* functor);
};
ConcreteA.h
class ConcreteA
{
};
ASerializationFunctor.cc
class ASerializationFunctor : public SerializationFunctor
{
virtual Base* operator(FILE* in)
{
// Restore ConcreteA and return a pointer.
}
};
bool dummy = registerSerializationFunction("ConcreteA", new ASerializationFunctor());
ConcreteB.h
class ConcreteB
{
};
BSerializationFunctor.cc
class BSerializationFunctor : public SerializationFunctor
{
virtual Base* operator(FILE* in)
{
// Restore ConcreteB and return a pointer.
}
};
bool dummy = registerSerializationFunction("ConcreteB", new BSerializationFunctor());