What would be the syntax to inherit constructors (some of them are template) from a class template in C++11 ?
template <class T>
struct Base
{
using type = T;
explicit constexpr Base(const type& x): value{x} {};
template <class U> explicit constexpr Base(U&& x): value{std::forward<U>(x)} {};
type value;
}
struct Derived: Base<bool>
{
using Base::Base<bool>; // Does not seem to work ?!?
}
You derive from Base<bool>. So your base class is Base<bool>, and inheriting the constructors is done via
using Base<bool>::Base;
Live on Coliru
You do not need Base<bool> after the ::, in fact the code doesn't compile if you put it. The constructors are still referred to as Base, and not Base<bool>. This is consistent with referring to member functions of class templates: you use e.g. void Foo<int>::f() and not void Foo<int>::f<int>() to refer to the Foo's member function f().
Related
I have a class template that inherits the constructors of the base class template. (As for c++20) Is there a way to deduce the template arguments of the derived class from the constructor arguments of base?
If I specify the type explicitly, that works. Or if I reimplement the constructor and call the constructor of base, that also would work but is there a way to do without that?
template<typename T>
struct CTestBase
{
using Type = T;
CTestBase() = default;
CTestBase(T t){}
};
template<typename T>
struct CTestDer : public CTestBase<T>
{
using CTestBase<T>::CTestBase;
};
void test()
{
//CTestDer der(int{}); //ERROR
CTestDer<int> der(int{}); //OK
}
You can add a user-defined deduction guide:
#include <utility>
template<typename T>
struct CTestBase
{
using Type = T;
CTestBase() = default;
CTestBase(T t){}
};
template<typename T>
struct CTestDer : public CTestBase<T>
{
using CTestBase<T>::CTestBase;
};
template<typename T>
CTestDer(T &&t) -> CTestDer<std::remove_cvref_t<T>>;
void test()
{
CTestDer der(int{}); // OK now.
}
With a little bit more work it should be possible to:
Use a variadic template in the deduction guide
Have the deduction guide use decltype to construct, using its own deduction guide, the superclass
Use a specialization to figure out the superclass's template parameters
Use that to construct the subclass, to deduce it
This should handle anything. But this will be a lot of work. For this simple use case, and if it's not expected that the superclass will change much, this would be overkill.
but is there a way to do without that?
Yes, just add user-defined deduction guides for CTestDer:
template<typename T>
CTestDer(T) -> CTestDer<T>;
Demo
Just curious, is it ever possible to inherit from a template class and in constructor of the derived class, call constructor of the base class which is also templated and has no arguments to deduce its types from?
template<typename T>
struct Base {
template<typename D>
Base() { // no argument of type D to infer from
static_assert(std::is_same<T,D>::value, "");
}
};
struct Derived : Base<int> {
Derived() : Base<int>::Base<int>() {} // is there a way to write it correctly?
};
I can replace template constructor by a template method in my particular case, but still it is an interesting question about the language flexibility.
What the C++ standard says about this (section 14.8.1):
[ Note: Because the explicit template argument list follows the function template name, and because conversion member function templates and constructor member function templates are called without using a function name, there is no way to provide an explicit template argument list for these function templates. — end note ]
It's a note, not a rule, because it actually is a consequence of two other rules, one in the same section:
Template arguments can be specified when referring to a function template specialization by qualifying the function template name with the list of template-arguments in the same way as template-arguments are specified in uses of a class template specialization.
and from 12.1
Constructors do not have names.
The template arguments of constructor templates must be deduced from their arguments, it's not possible to explicitly specify template arguments for constructors.
As such, have Base take a dummy parameter that deduces the argument:
template <typename T>
struct dummy { }; // to prevent instantiation of T
template <typename T>
struct Base
{
template <typename D>
Base(dummy<D>)
{
static_assert(std::is_same<T, D>::value, "");
}
};
struct Derived : Base<int>
{
Derived() : Base<int>(dummy<int>{}) { }
};
By the way the question is formulated it looks going towards a nonsensical paranoia.
Just think for plain classes:
class Base
{
public:
Base() {}
};
class Derived: public Base
{
public:
Derived() //< default ctor
:Base //< this is the Base type
() //< this selects what ctor to call
{}
};
Note that you call :Base(), that resolve into Base::Base(), not :Base::Base()
Now, by templetizing Base::Base() you are in fact trying to admit that there can be many different default ctor (with ()) for Base. That's a nonsense respect ot the concept itself of "default".
Even if Base is not by itself a template, this is not possible:
class Base
{
public:
template<class T>
Base() {} //< are there infinite way to default construct Base ?!?
};
Base b; //< so how is b constructed ?
Thing gets only apparently different with varadics:
template<class T>
class Base
{
public:
template<class... S>
Base(S&&... s) { /* something to do */ }
};
class Derived: public Base<int>
{
public:
template<class... S>
Derived(S&&... s) //< Derived varadicly initialized
:Base //< base type ...
(std::forward<S>(s)...) //< ... to initialize with what
{}
};
Note that in case s is empty you are in fact calling Base::Base() from Derived()::Derived(), templetized with <> (no args)
I have a templatized class like so :
template<typename T>
class A
{
protected:
std::vector<T> myVector;
public:
/*
constructors + a bunch of member functions here
*/
}
I would like to add just ONE member function that would work only for 1 given type of T. Is it possible to do that at all without having to specialize the class and reimplement all the other already existing methods?
Thanks
The simplest and cleanest solution is to use a static_assert() in the body of a method, rejecting other types than the selected one (in the below example only integers are accepted):
#include <type_traits>
#include <vector>
template <typename T>
class A
{
public:
void onlyForInts(T t)
{
static_assert(std::is_same<T, int>::value, "Works only with ints!");
}
protected:
std::vector<T> myVector;
};
int main()
{
A<int> i;
i.onlyForInts(1); // works !
A<float> f;
//f.onlyForInts(3.14f); // does not compile !
}
OK CASE DEMO
NOK CASE DEMO
This utilizes the fact that a compiler instantiates a member function of a class template only when one is actually used (not when the class template is instantiated itself). And with the above solution, when a compiler tries to do so, it fails due to the execution of a static_assert.
C++ Standard Reference:
§ 14.7.1 Implicit instantiation [temp.inst]
Unless a function template specialization has been explicitly instantiated or explicitly specialized, the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist. Unless a call is to a function template explicit specialization or to a member function of an explicitly specialized class template, a default argument for a function template or a member function of a class template is implicitly instantiated when the function is called in a context that requires the value of the default argument.
[ Example:
template<class T> struct Z {
void f();
void g();
};
void h() {
Z<int> a; // instantiation of class Z<int> required
Z<char>* p; // instantiation of class Z<char> not required
Z<double>* q; // instantiation of class Z<double> not required
a.f(); // instantiation of Z<int>::f() required
p->g(); // instantiation of class Z<char> required, and
// instantiation of Z<char>::g() required
}
Nothing in this example requires class Z<double>, Z<int>::g(), or Z<char>::f() to be implicitly
instantiated. — end example ]
Yes, it's possible in C++03 with CRTP (Curiously recurring template pattern):
#include <numeric>
#include <vector>
template<typename Derived, typename T>
struct Base
{
};
template<typename Derived>
struct Base<Derived, int>
{
int Sum() const
{
return std::accumulate(static_cast<Derived const*>(this)->myVector.begin(), static_cast<Derived const*>(this)->myVector.end(), int());
}
};
template<typename T>
class A : public Base<A<T>, T>
{
friend class Base<A<T>, T>;
protected:
std::vector<T> myVector;
public:
/*
constructors + a bunch of member functions here
*/
};
int main()
{
A<int> Foo;
Foo.Sum();
}
As an alternative solution, which works also in plain C++03 (as opposed to static_assert or enable_if solutions), you may add extra defaulted template argument which will let you have both
specialized and unspecialized version of class. Then you can inherit your specialized version from the unspecialized one.
Here is a sample snippet:
#include <vector>
template<typename T, bool unspecialized = false>
class A
{
protected:
std::vector<T> myVector;
public:
void setVec(const std::vector<T>& vec) { myVector = vec; }
/*
constructors + a bunch of member functions here
*/
};
template<>
class A<int, false> : public A<int, true>
{
public:
int onlyForInt() {
return 25;
}
};
int main() {
// your code goes here
std::vector<int> vec;
A<int> a;
a.setVec(vec);
a.onlyForInt();
return 0;
}
The drawbacks of this solution is the need to add constructor forwarders, if class
has non-trivial constructors.
The static_assert technique by #PiotrS. works nicely. But it's also nice to know that you can specialize a single member function without code duplication. Just give the generic onlyForInts() an empty no-op implementation, and specialize it out-of-class for int
#include <vector>
template <typename T>
class A
{
public:
void onlyForInts(T t)
{
// no-op
}
protected:
std::vector<T> myVector;
};
template<>
void A<int>::onlyForInts(int t)
{
// works
}
int main()
{
A<int> i;
i.onlyForInts(1); // works !
A<float> f;
f.onlyForInts(3.14f); // compiles, but does nothing !
}
Live Example.
This technique comes in handy if you want to have int specific behavior without completely disabling the generic behavior.
One approach not given yet in the answers is using the standard library std::enable_if to perform SFINAE on a base class that you inherit to the main class that defines appropriate member functions.
Example code:
template<typename T, class Enable = void>
class A_base;
template<typename T>
class A_base<T, typename std::enable_if<std::is_integral<T>::value>::type>{
public:
void only_for_ints(){/* integer-based function */}
};
template<typename T>
class A_base<T, typename std::enable_if<!std::is_integral<T>::value>::type>{
public:
// maybe specialize for non-int
};
template<typename T>
class A: public A_base<T>{
protected:
std::vector<T> my_vector;
};
This approach would be better than an empty function because you are being more strict about your API and better than a static_cast because it simply won't make it to the inside of the function (it won't exist) and will give you a nice error message at compile time (GCC shows "has no member named ‘only_for_ints’" on my machine).
The downside to this method would be compile time and code bloat, but I don't think it's too hefty.
(don't you dare say that C++11 requirement is a down-side, we're in 2014 god-damnit and the next standard has even be finalized already!)
Also, I noticed, you will probably have to define my_vector in the base class instead of the final because you probably want to handle that data within the member function.
A nice way to do that without duplicating a bunch of code is to create a base base class (good god) and inherit that class in the base class.
Example:
template<typename T>
class base_data{
protected:
std::vector<T> my_vector;
};
template<typename T>
class A_base<T, typename std::enable_if<std::is_integral<T>::value>::type>: public base_bata<T>{
public:
void only_for_ints(){/* phew, finally. fiddle around with my_vector! */}
};
// non-integer A-base
template<typename T>
class A: public A_base<T>{
protected:
// helper functions not available in base
};
That does leave a horrible looking multiple-inheritance scheme, but it is very workable and makes it easy to define members based on template parameters (for future proofing).
People often don't like multiple-inheritance or how complicated/messy SFINAE looks, but I couldn't live without it now that I know of it: the speed of static code with the polymorphism of dynamic code!
Not sure where I found this, but you can use = delete; as the function definition inside the class, thereby deleting the function for the general case, and then explicitly specialize outside the class:
template <typename T>
struct A
{
auto int_only(T) -> void = delete;
};
template <> auto A<int>::int_only(int) -> void {}
int main()
{
auto a_int = A<int>{};
auto a_dbl = A<double>{};
a_int.int_only(0);
// a_dbl.int_only(3.14); error: call to deleted member function
}
https://en.cppreference.com/w/cpp/language/function#Deleted_functions
This question is considering explicit instanciation of template classes.
Consider a template class B<T> derived from another template class A<T>. I want to explicitly instanicate B<T> because its methods are to be called from dynamic linking, so the methods must be instanciated although they are not called in the code itself. Of course, also methods inherited from A<T> will be called, so they must be instanciated as well.
It seems that C++ does NOT instanciate base classes when explicitly instanciating a template class, as asked in this question:
Do Explicit Instantiations of C++ Class Templates Instantiate Dependent Base Classes?
Example:
template<typename T>
class A{ void foo(){...} };
template<typename T>
class B : public A<T> {}
template class B<int>; // This will NOT instanciate A<int>::foo()!!!
Of course, I also need to instanciate all base classes. However, I don't want to burden the client code with this because the class hierarchy may be very deep. Consider a class hierarchy involving 10 or more template classes. The client should not be urged to write 10 explicit template instanciations. This is not only a lot of writing; it will also break when I introduce changes to the class hierarchy.
Instead, I want to achieve somehow that whenever B<T> is instanciated, then so are all its base classes. I tried simply instanciating the base class in B itself like this:
template<typename T>
class B : public A<T> {
template class A<T>; // Does not compile!
}
But this does not compile. Are there other ways that could achive this?
Maybe not elegant but at least workable: provide a macro to instantiate the template and require the user to use the macro in stead of manual instantiation:
// in A.hpp
#define INSTANTIATE_A(T) template class A<T>;
// in B.hpp
#define INSTANTIATE_B(T) \
INSTANTIATE_A(T) \
template class B<T>;
And if you prefer "polluting" the class interface to enforcing the use of an instantiation macro: add a protected member that calls all other member functions of the template and the version in the base class. Example:
template<typename T>
class A
{
void foo() {...}
protected:
void instantiate() { foo(); }
};
template<typename T>
class B : public A<T>
{
void bar() {...}
protected:
void instantiate() { A<T>::instantiate(); bar(); }
};
template class B<int>; // Now works as expected
Update:
Alternative to the second solution: take the function pointer of all members and save them to a temporary variable:
template<typename T>
class A
{
void foo() {...}
protected:
void instantiate() { void (A::*p)() = &A::foo; }
};
template<typename T>
class B : public A<T>
{
void bar() {...}
protected:
void instantiate() { A<T>::instantiate(); void (B::*p)() = &B::foo; }
};
Let's say we have a class, MyParent:
class MyParent
{
public:
template<namespace T>
MyParent()
{
T* Something;
}
};
And a derived class, which uses this constructor:
class MyDerived : public MyParent
{
public:
MyDerived()
: MyParent<int>()
{
}
};
Then I get a compiling error, because there's ambiguity. The compiler thinks that the int is a template argument to the class, not the constructor.
How do I specify that I want the int to be an argument to the constructor?
It is not possible. From the standard section 14.8.1 Explicit template argument, it notes:
[Note: because the explicit template argument list follows the function template name, and because conversion member function templates and constructor member function templates are called without using a
function name, there is no way to provide an explicit template argument list for these function templates. ]
As noted in the comments, you would need to have the constructor take a parameter of type T (or const T &), and then have MyDerived call MyParent::MyParent with a paremeter of type int.
Note that your question is not particular to inheritance. Given your code example, you cannot instantiate MyParent at all, either because it doesn't accept a template argument list or because it has no default constructor.
In order to instantiate MyParent with a constructor template, you need to provide some way for the compiler to know the template argument, and you can't do that with a no-argument constructor. You need to give MyParent's constructor a parameter. Here's an example based on code from Alf P. Steinbach:
template <typename T>
struct UseMethodsOf {};
class MyParent
{
public:
template <typename T>
MyParent(UseMethodsOf<T>)
{
T* Something;
}
};
class MyDerived: public MyParent
{
public:
MyDerived()
: MyParent(UseMethodsOf<int>())
{
}
};