Let's suppose I have some C++ abstract class and all its inherited classes have different constructors:
class Abstract{
//don't worry, there is some pure virtual method here
}
class A : public Abstract {
public:
A (int Afirst, std::string Asecond, int Athird) {...}
...
}
class B : public Abstract {
public
B (double Bfirst, std::int Bsecond) {...}
...
}
class C : public Abstract {
public
C (std::string Cfirst, double Csecond, int Cthird, float Cfourth) {...}
}
As you can see, all the inherited class have (possibly) different constructors.
Now, I want to write a generic main(), something like:
int main (int argc, char *argv[]){
if(argc < 2){
std::cerr<<"Too few arguments!"<<std::endl;
exit(1);
}
std::string type = argv[1];
Abstract *abs;
if(!type.compare("A"){
if(argc < 5){
std::cerr<<"Too few arguments for A!"<<std::endl;
exit(1);
}
abs = new A(atoi(argv[2]), argv[3], argv[4]);
}
//similar for B, C, D
}
I wonder if there is a best way to do this, for example passing directly char *argv[] to each constructor and make all the checks inside the constructor (and eventually throwing an exception as described here).
You may do something like that to be generic:
// functions to convert const char* to given type
template <typename T> T To(const char*);
template <> int To(const char* s) { return atoi(s); }
template <> const char* To(const char* s) { return s; }
template <> std::string To(const char* s) { return s; }
// ...
// Your classes:
struct Abstract { virtual ~Abstract() = default; };
struct A : Abstract { A (int, std::string, int) {}};
struct B : Abstract { B (int, int) {}};
// ...
namespace detail
{
// Helper functions for the factory.
template <typename T, typename Tuple, std::size_t... Is>
std::unique_ptr<Abstract> make_abstract(const char*argv[], std::index_sequence<Is...>)
{
return std::make_unique<T>(To<std::tuple_element_t<Is, Tuple>>(argv[2 + Is])...);
}
template <typename T, typename Tuple>
std::unique_ptr<Abstract> make_abstract(int argc, const char*argv[])
{
constexpr int tuple_size = std::tuple_size<Tuple>::value;
if (argc < tuple_size) {
throw std::runtime_error("Too few arguments");
}
return make_abstract<T, Tuple>(argv, std::make_index_sequence<tuple_size>());
}
}
// The public factory
std::unique_ptr<Abstract> make_abstract(int argc, const char*argv[])
{
if (argc == 1) {
return nullptr;
}
const std::string name = argv[1];
if (name == "A") {
return detail::make_abstract<A, std::tuple<int, std::string, int>>(argc, argv);
} else if (name == "B") {
return detail::make_abstract<B, std::tuple<int, int>>(argc, argv);
}
// ...
return nullptr;
}
Related
I would like to define a variadic template class BaseA, which has a variadic function execute(...). The subclasses extend execute(...) with definite arguments.
I try a demo code, but it has type conversion error, how to collect all subclasses and use execute?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// template base class A
template <typename ... Types>
class BaseA {
public:
virtual int execute(Types ...) = 0;
};
// subclass 1
class SubA1 :public BaseA<int> {
public:
int execute(int b) override {
//...
printf("sub-1 has int %d", b);
return 0;
}
};
// subclass 2
class SubA2 :public BaseA<int, string> {
public:
int execute(int b, string c) override {
//...
printf("sub-2 is int:%d and str:%s", b, c.c_str());
return 0;
}
};
// SubA3 may has other arguments
int main() {
vector<BaseA<int> *> as(3);
as[0] = (BaseA<int> *) new SubA1();
as[1] = (BaseA<int, string> *) new SubA2(); // error here
as[0]->execute(1);
as[1]->execute(1, "2");
// as[2] ...
return 0;
}
Thanks for any ideas.
Use another base for the array and typecast when using.
#include <iostream>
#include <string>
#include <vector>
class BaseAA {
public:
BaseAA(){
}
~BaseAA(){
}
template <typename ... Types>
int executeAA(Types ...){
std::cout << "BaseAA";
return 0;
}
};
// template base class A
template <typename ... Types>
class BaseA: public BaseAA {
public:
using BaseType = BaseA<Types...>;
virtual int execute(Types ... ts){
std::cout << "BaseA ";
return executeAA<Types ...>(ts...);
};
};
// subclass 1
class SubA1 :public BaseA<int> {
public:
int execute(int b) override {
//...
BaseType::execute(b);
std::cout << "sub-1 has int " << b << '\n';
return 0;
}
};
// subclass 2
class SubA2 :public BaseA<int, std::string> {
public:
int execute(int b, std::string c) override {
//...
BaseType::execute(b, c);
std::cout << "sub-2 is int:"<<b<<" and str:" << c;
return 0;
}
};
// SubA3 may has other arguments
int main() {
std::vector<BaseAA *> as(3);
as[0] = new SubA1();
as[1] = new SubA2(); // error here
static_cast<SubA1::BaseType*>(as[0])->execute(1);
static_cast<SubA2::BaseType*>(as[1])->execute(1, "2");
// as[2] ...
return 0;
}
If you don't want the typecast then you can use a single parameter type
with derived classes for the different groups of parameters.
#include <iostream>
#include <vector>
#include <tuple>
using namespace std::string_literals;
template <class O, class F, class Tuple, std::size_t... I>
constexpr decltype(auto) apply_this(O* o, F&& f, Tuple&& t, std::index_sequence<I...>) {
return (o->*f)(std::get<I>(t)...);
}
struct ParamsBase {
};
class BaseAA {
public:
BaseAA(){
}
~BaseAA(){
}
virtual int execute(const ParamsBase& p) = 0;
};
template<typename ... Ts>
struct Params: public ParamsBase {
using Tuple_t = std::tuple<Ts...>;
static size_t const count = sizeof ... (Ts);
Tuple_t p;
Params(Tuple_t&& p): p(p){
}
static Params const& getParams(const ParamsBase& p) {
return static_cast<const Params&>(p);
}
static Tuple_t const& getTuple(const ParamsBase& p) {
return getParams(p).p;
}
};
// template base class A
template <typename ... Types>
class BaseA: public BaseAA {
public:
using Params_t = Params<Types...>;
virtual int execute(const ParamsBase& pin) override {
return apply_this(this, (int(BaseA::*)(Types...))(&BaseA::execute), Params_t::getTuple(pin), std::make_index_sequence<Params_t::count>{});
}
virtual int execute(Types ... t){
std::cout << " default ";
return 0;
}
};
// subclass 1
class SubA1 :public BaseA<int> {
public:
virtual int execute(int b) override {
BaseA::execute(b);
std::cout << " sub-1 has int " << b << '\n';
return 0;
}
};
// subclass 2
class SubA2 :public BaseA<int, std::string> {
public:
virtual int execute(int b, std::string c) override {
BaseA::execute(b, c);
std::cout << " sub-2 is int: "<<b<<" and str: " << c;
return 0;
}
};
// SubA3 may has other arguments
int main() {
std::vector<BaseAA *> as(3);
as[0] = new SubA1();
as[1] = new SubA2();
as[0]->execute(Params(std::make_tuple(1)));
as[1]->execute(Params(std::make_tuple(1, "2"s))); // s makes std::string
// as[2] ...
return 0;
}
https://godbolt.org/z/tueU2f
When you create a
vector<BaseA<> *> as(2);
you are expecting that vector can accept any type. Which is, I believe, wrong in C++. The vector can accept only type.
When you use template to instantiate the Base class type, the compiler will generate following class hierarchy for you.
class BaseA_int {
public:
virtual int execute(int) = 0;
};
// subclass 1
class SubA1 :public BaseA_int {
public:
int execute(int b) override {
//...
return 0;
}
};
class BaseA_int_string
{
public:
virtual int execute(int, string) = 0;
};
// subclass 2
class SubA2 :public BaseA_int_string {
int execute(int b, string c) override {
//...
return 0;
}
};
And here you can see that derived classes uses different base classes. As the vector can only one type, Base<> *, but your are assigning a type of Base to it, the compiler gives an error.
So Base and Base are entirely two different base classes.
The below will compile without any issue, but it cannot accept Base
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// template base class A
template <typename ... Types>
class BaseA {
public:
virtual int execute(Types ...) = 0;
};
// subclass 1
class SubA1 :public BaseA<int> {
int execute(int b) override {
//...
return 0;
}
};
// subclass 2
class SubA2 :public BaseA<int, string> {
int execute(int b, string c) override {
//...
return 0;
}
};
int main() {
vector<BaseA<int> *> as(2);
as[0] = (BaseA<int> *) new SubA1(); // type conversion error here
as[0]->execute(1);
return 0;
}
How to make an optional template parameter with the base class using CRTP in the following code ?
template <unsigned int BYTES, OPTIONAL typename DerivedPrinter = MonoPrinter> //DerivedPrinter should be optional. If it is not specified then it should default to MonoPrinter.
class MonoPrinter
{
protected:
unsigned char CtrlCodes[BYTES] = { 0xFF }; //A code to initialize the printer
public:
MonoPrinter()
{
}
DerivedPrinter& print(const char* d)
{
for (int i=0; i<sizeof(CtrlCodes); i++)
SendCtrlCode(CtrlCodes[i]); //Initialize the printer and send additional control codes for color, font, etc...
printf("Print Me: %s\n", d); //This would actually send the string of chars to the printer (not to stdout) for printing
return static_cast<DerivedPrinter&>(*this); //Return a reference to the Derived Printer a la CRTP
}
};
template <unsigned int BYTES>
class ColorPrinter : public MonoPrinter<BYTES, ColorPrinter>
{
public:
ColorPrinter() : MonoPrinter()
{
static_assert(sizeof(CtrlCodes) >= 4);
CtrlCodes[1] = 0xAA;
CtrlCodes[2] = 0xBB;
CtrlCodes[3] = 0xC0;
}
ColorPrinter& SetColor(unsigned char c)
{
CtrlCodes[3] = c;
return *this;
}
};
void main(void)
{
MonoPrinter<1> iMonoPrinter;
ColorPrinter<4> iColorPrinter;
iMonoPrinter.print("Hello World").print(" we have no color");
iColorPrinter.print("Hello World").SetColor(BLUE).print(" in Living Color");
}
P.S.
The above code is a contrived and abridged for simplicity. The "BYTES" template parameter is not optional and it always must be specified.
I have other problems with this code, but the main one is how to make the "DerivedPrinter" template parameter optional, so it does not always have to be specified ...and when it is not - it should default to the base class itself.
I guess you can (see code below), but I think it's not necessary in this case (see second example).
First example, with the optional template parameter (note that here the PrinterTpl template inherits directly from the concrete BasePrinter, so all derived classes, MonoPrinter and ColorPrinter here, are inheriting from BasePrinter):
template <unsigned int BYTES>
class BasePrinter
{
protected:
unsigned char CtrlCodes[BYTES] = { 0xFF };
public:
BasePrinter()
{
SendCtrlCode(CtrlCodes[0]); //Initialize the printer
}
};
template <unsigned int BYTES, typename DerivedPrinter = BasePrinter<BYTES>> //DerivedPrinter should be optional. If it is not specified then it should default to PrinterTpl.
class PrinterTpl : public BasePrinter<BYTES>
{
public:
PrinterTpl() : BasePrinter<BYTES>()
{
}
DerivedPrinter& print(const char* d)
{
printf("Data: %s\n", d);
return static_cast<DerivedPrinter&>(*this); //Return a reference to the Derived Printer a la CRTP
}
};
template <unsigned int BYTES>
class MonoPrinter : public PrinterTpl<BYTES, MonoPrinter<BYTES>>
{
public:
MonoPrinter() : PrinterTpl<BYTES, MonoPrinter<BYTES>>()
{
}
};
template <unsigned int BYTES>
class ColorPrinter : public PrinterTpl<BYTES, ColorPrinter<BYTES>>
{
public:
ColorPrinter() : PrinterTpl<BYTES, ColorPrinter<BYTES>>()
{
static_assert(sizeof(this->CtrlCodes) >= 4, "CtrlCodes too small");
this->CtrlCodes[1] = 0xC1;
this->CtrlCodes[2] = 0xC2;
this->CtrlCodes[3] = 0xC3;
}
ColorPrinter& SetColor(int c)
{
assert(c < sizeof(this->CtrlCodes));
SendCtrlCode(this->CtrlCodes[c+1]);
return *this;
}
};
Second example, no template optional parameter (here the template PrinterTpl doesn't need to inherit from a base):
template <unsigned int BYTES, typename ConcretePrinter>
class PrinterTpl
{
protected:
unsigned char CtrlCodes[BYTES] = { 0xFF };
public:
PrinterTpl()
{
SendCtrlCode(this->CtrlCodes[0]); //Initialize the printer
}
ConcretePrinter& print(const char* d)
{
printf("Data: %s\n", d);
return static_cast<ConcretePrinter&>(*this); //Return a reference to the Derived Printer a la CRTP
}
};
template <unsigned int BYTES>
class MonoPrinter : public PrinterTpl<BYTES, MonoPrinter<BYTES>>
{
public:
MonoPrinter() : PrinterTpl<BYTES, MonoPrinter<BYTES>>()
{
}
};
template <unsigned int BYTES>
class ColorPrinter : public PrinterTpl<BYTES, ColorPrinter<BYTES>>
{
public:
ColorPrinter() : PrinterTpl<BYTES, ColorPrinter<BYTES>>()
{
static_assert(sizeof(this->CtrlCodes) >= 4, "CtrlCodes too small");
this->CtrlCodes[1] = 0xC1;
this->CtrlCodes[2] = 0xC2;
this->CtrlCodes[3] = 0xC3;
}
ColorPrinter& SetColor(int c)
{
assert(c < sizeof(this->CtrlCodes));
SendCtrlCode(this->CtrlCodes[c+1]);
return *this;
}
};
If I am not mistaken, this should achieve your goal and it's cleaner in my opinion.
The key to being able to write MonoPrinter<1> instead of MonoPrinter<1,dummy> and making the 2nd template parameter optional was the following conditional typedef typenameinside the base class template:
typedef typename std::conditional< std::is_same<Derived, void >::value, MonoPrinter, Derived >::type DerivedPrinter; //Default to the MonoPrinter class if Derived == void
The code below now compiles without errors and does not require the creation of a 3rd class template. See: https://godbolt.org/g/awuck7
#include <type_traits>
#include <stdio.h>
#define BLUE 3
template <unsigned int BYTES, typename Derived = void>
class MonoPrinter
{
typedef typename std::conditional< std::is_same<Derived, void >::value, MonoPrinter, Derived >::type DerivedPrinter; //Default to the MonoPrinter class if Derived == void
protected:
unsigned char CtrlCodes[BYTES];
const unsigned char FinCode = 0xFF;
public:
void SendCtrlCode(unsigned char c)
{
printf("<%02X>", c); //This would actually send the string of control chars to the printer (not to stdout)
}
void InitializePrinter(void)
{
printf("\n");
SendCtrlCode(CtrlCodes[0]);
SendCtrlCode(0x00);
SendCtrlCode(FinCode);
}
MonoPrinter()
{
CtrlCodes[0] = 0xEE; //Set the default printer escape code
InitializePrinter();
}
MonoPrinter(unsigned char c)
{
CtrlCodes[0] = c; //A custom printer escape code
InitializePrinter();
}
DerivedPrinter& print(const char* d)
{
for (int i = 0; i < sizeof(CtrlCodes); i++)
SendCtrlCode(CtrlCodes[i]); //Initialize the printer and send additional control codes for color, font, etc...
SendCtrlCode(FinCode);
printf("%s", d); //This would actually send the string of chars to the printer (not to stdout) for printing
return static_cast<DerivedPrinter&>(*this); //Return a reference to the Derived Printer a la CRTP
}
int FooFn()
{
return 333;
}
};
template <unsigned int BYTES>
class ColorPrinter : public MonoPrinter<BYTES, ColorPrinter<BYTES>>
{
protected:
using MonoPrinter<BYTES, ColorPrinter<BYTES>>::CtrlCodes;
//using MonoPrinter<BYTES, ColorPrinter<BYTES>>::FinCode;
public:
//using MonoPrinter<BYTES, ColorPrinter<BYTES>>::MonoPrinter;
using MonoPrinter<BYTES, ColorPrinter<BYTES>>::FooFn;
//using MonoPrinter<BYTES, ColorPrinter<BYTES>>::InitializePrinter;
//using MonoPrinter<BYTES, ColorPrinter<BYTES>>::SendCtrlCode;
ColorPrinter()
{
static_assert(sizeof(this->CtrlCodes) >= 4, "CtrlCodes too small");
CtrlCodes[1] = 0xDD;
CtrlCodes[2] = 0xEE;
CtrlCodes[3] = 0xC0; //Default Color value
}
ColorPrinter(unsigned char c) : MonoPrinter<BYTES, ColorPrinter<BYTES>>::MonoPrinter(c)
{
static_assert(sizeof(this->CtrlCodes) >= 4, "CtrlCodes too small");
CtrlCodes[1] = 0xDD;
CtrlCodes[2] = 0xEE;
CtrlCodes[3] = 0xC0; //Default Color value
}
ColorPrinter& SetColor(unsigned char c)
{
CtrlCodes[3] = c;
return *this;
}
int BooFn()
{
return FooFn() + 1;
}
};
int main(void)
{
MonoPrinter<1> iMonoPrinter;
ColorPrinter<4> iColorPrinter(0xCC);
iMonoPrinter.print("Hello World").print(" we have no color \n");
iColorPrinter.print("Hello World").SetColor(BLUE).print(" in Living Color \n");
printf(" %d\n", iColorPrinter.FooFn());
printf(" %d\n", iColorPrinter.BooFn());
return 0;
}
I have a class like the following:
template<typename ... TTypes>
class Composite {
public:
//Composite() : null(true) { }
Composite(TTypes... values) : values(std::make_tuple(values...)), null(false) { }
private:
bool null;
std::tuple<TTypes...> values;
};
int main(int argc, char *argv[]) {
Composite<int, char, int> a1;
}
But this leads to an error because the second constructor would override the first one with TTypes = {}. Is there any way to keep the empty constructor?
Best,
Moritz
Since none of the existing answers so actually solve the problem, but there is a solution by Piotr Skotnicki hidden in the comments, I'm just gonna repost it here for visibility:
#include <tuple>
#include <type_traits>
template<typename ... TTypes>
class Composite {
public:
Composite() : null(true) { }
template <std::size_t N = sizeof...(TTypes), typename std::enable_if<(N>0), int>::type = 0>
Composite(TTypes... values) : values(std::make_tuple(values...)), null(false) { }
private:
bool null;
std::tuple<TTypes...> values;
};
int main(int argc, char *argv[]) {
Composite<int, char, int> a1;
Composite<> a2;
}
I am not sure whether the following work around is an option for you:
template<typename ... TTypes>
class Composite : public ValueSet {
public:
Composite(TTypes... values) { }
};
template<>
class Composite<> : public ValueSet {
public:
Composite() : ValueSet() { }
};
but it works.
The case where your parameter pack TTypes is empty makes the default constructor ambiguous. If you plan to provide at least 1 parameter, then you can specify an additional parameter:
template<typename TType, typename ... TTypes>
class Composite {
public:
Composite() : null(true) { }
Composite(TType first, TTypes... rest) :
values(std::make_tuple(first,rest...)),
null(false)
{
}
private:
bool null;
std::tuple<TType,TTypes...> values;
};
int main(int argc, char *argv[]) {
Composite<int, char, int> a1;
}
However, take into account that this functionality is provided by std::optional, so it should be better using it.
template < typename... TTypes >
using Composite = std::optional<std::tuple<TTypes...>>;
sorry for the title, it's quite confusing to explain, but it will be more clear with example
In C, I used to write program like this :
void createClassA()
{
}
void createClassB()
{
}
typedef struct {
const char *name;
void (*create_class)();
} MapList;
MapList mapList[] = {
{"A", &createClassA},
{"B", &createClassB },
};
void create(const char *name)
{
int i=0;
for (i=0; i < sizeof(mapList) / sizeof(MapList); i++) {
if (strcmp(name, mapList[i].name) == 0) mapList[i].create_class();
}
}
int main(int argc, char** argv)
{
if (argc < 1) return -1;
create(argv[1]);
return 0;
}
So if I have more types, all I have to do is to create the function itself and add it to the mapList.
but in C++, the best I can do is something like:
#include <iostream>
class myA{};
class myB{};
class myC{};
class Base
{
public:
template<class T>
void createClass()
{
T* t = new T();
//t->doSomethingUseful();
}
void create(const std::string name)
{
if (name=="A") createClass<myA>();
else if (name=="B") createClass<myB>();
else if (name=="C") createClass<myC>();
}
};
int main(int agrc, char** argv)
{
if (argc<1) return -1;
Base b;
b.create(argv[0]);
return 0;
}
Can I create something like :
typedef struct {
std::string name;
[CLASS_TYPE] class_type; <== I don't know how
} MapList;
so I can create a mapping List but fill it with class Type, something like
mapList[] = {
{"A", myA},
{"B", myB},
{"B", myC},
};
and then I can create iteration like:
for (int i=0; i<sizeof(mapList) / sizeof(MapList); i++) {
if (mapList[i].name == name) b.createClass<mapList[i].classType>();
}
Thanks guys :)
In C++ you can use std::function in the <functional> standard header. Specifically, your example for the map list can be written as (with lambdas):
std::map<std::string, std::function<void()>> mapList;
mapList["A"] = []() { /* ... */ };
mapList["B"] = []() { /* ... */ };
or just (without lambdas):
void createClassA() {}
void createClassB() {}
std::map<std::string, std::function<void()>> mapList;
mapList["A"] = createClassA;
mapList["B"] = createClassB;
In C++ you could do that with virtual functions:
struct ClassMaker {
virtual void create_class() = 0;
};
struct ClassMakerA : public ClassMaker {
virtual void create_class() {
...
}
};
struct ClassMakerB : public ClassMaker {
virtual void create_class() {
...
}
};
Now you can create a std::map<std::string,ClassMaker*> with your "factories", like this:
ClassMakerA makerA;
ClassMakerB makerB;
// This syntax requires C++11
std::map<std::string,ClassMaker*> makers = {
{"A", &makerA}
, {"B", &makerB}
};
Finally, you can now call create_class() based on a std::string value, like this:
void create(const std::string &name) {
ClassMaker *maker = makers[name];
if (maker) maker -> create_class();
}
You could look for Boost::any, which provides "a variant value type".
You can use derived classes and object factory, something like that would work. You can improve it by make create method to return smart pointers and make A and B constructors private to avoid creating objects on the stack.
class Base
{
static Base* create(const char *name);
};
class A : public Base
{
};
class B : public Base
{
};
Base* Base::create(const char *name)
{
if(strcmp(name,"A")==0)
return new A();
if(strcmp(name,"B")==0)
return new B();
return 0;
}
int main(int agrc, char** argv)
{
if (argc<1) return -1;
Base *b = Base::create(argv[0]);
return 0;
}
It is somewhat similar to solution by #dasblinkenlight, but avoid virtual functions overhead.
I need to call different versions of a template member function with the same arguments based on certain static members of the template parameters. Here's a sort of simplified version of what I need to do:
class A {
public:
//...
static const char fooString[];
};
const char A::fooString[] = "This is a Foo.";
class B {
public:
//...
static const char barString[];
};
const char B::barString[] = "This is a Bar.";
class C {
public:
//...
static const char fooString[];
};
const char C::fooString[] = "This is also a Foo.";
//Many other classes which have either a fooString or a barString
void doFoo(const char*s) { /*something*/ }
void doBar(const char*s) { /*something else*/ }
template<class T>
class Something {
public:
//This version should be called if T has a static member called "fooString",
//so it should be called if T is either class A or C
void doSomething() { doFoo(T::fooString); }
//This version should be called if T has a static member called "barString",
//so it should be called if T is class B
void doSomething() { doBar(T::barString); }
};
void someFunc()
{
Something<A> a;
Something<B> b;
Something<C> c;
a.doSomething(); //should call doFoo(A::fooString)
b.doSomething(); //should call doBar(B::barString)
c.doSomething(); //should call doFoo(C::fooString)
}
How would I achieve this?
A possible solution:
#include <iostream>
#include <type_traits>
class A {
public:
//...
static const char fooString[];
};
const char A::fooString[] = "This is a Foo.";
class B {
public:
//...
static const char barString[];
};
const char B::barString[] = "This is a Bar.";
class C {
public:
//...
static const char fooString[];
};
const char C::fooString[] = "This is also a Foo.";
void doFoo(const char*s) { std::cout << "doFoo: " << s << "\n"; }
void doBar(const char*s) { std::cout << "doBar: " << s << "\n"; }
template<class T>
class Something {
public:
//This version should be called if T has a static member called "fooString",
//so it should be called if T is either class A or C
template <typename TT = T, typename std::enable_if<TT::fooString != 0, bool>::type = false>
void doSomething() { doFoo(T::fooString); }
//This version should be called if T has a static member called "barString",
//so it should be called if T is class B
template <typename TT = T, typename std::enable_if<TT::barString != 0, bool>::type = false>
void doSomething() { doBar(T::barString); }
};
int main()
{
Something<A> a;
Something<B> b;
Something<C> c;
a.doSomething(); //should call doFoo(A::fooString)
b.doSomething(); //should call doBar(B::barString)
c.doSomething(); //should call doFoo(C::fooString)
}
Output:
doFoo: This is a Foo.
doBar: This is a Bar.
doFoo: This is also a Foo.