Let say i have two classes MyClass_one
, MyClass_two
And i have function that accept only them as first parameter
template<typename T,typename ...Ts>
void doSomething(T one, Ts...two){}
Now to make it simple, if parameter one
is MyClass_one
it should print "im one" if its MyClass_two
it should print "im two".
How to actually achieve this? The only solution i have came up with is really ugly and does not containt compile error throwing:
template<typename T> isOne{ static const bool value = false}
template<> isOne<MyClass_one>{ static const bool value = true}
template<typename T> isTwo{ static const bool value = false}
template<> isTwo<MyClass_two>{ static const bool value = true}
template<typename T, typename ... Ts>
void doSomething(T one, Ts...two){
if( isOne<T>::value ) { cout << "im one" << endl;}
else if ( isTwo<T>::value){ cout <<"im two" << endl;}
}
However how to implement the compiler error check without overloading (multiple definition of doSomething()
function) e.g the function will not compile if something else than MyClass_one
or MyClass_two
is passed.
thanks for help.
If you can use C++17, you can use if constexpr
:
template<typename T, typename ... Ts>
void doSomething(T one, Ts...two){
if constexpr ( isOne<T>::value ) { cout << "im one" << endl;}
else if constexpr ( isTwo<T>::value){ cout <<"im two" << endl;}
}
Of course, isOne<T>::value
and isTwo<T>::value
need to be static constexpr
variables.
If you want to check the types of the first function argument, the same approach holds, only there is no need for something like isOne
and isTwo
, you can use std::is_same_v
to see if the first argument is MyClassOne
or MyClassTwo
:
#include <iostream>
#include <type_traits>
#include <vector>
class MyClassOne {};
class MyClassTwo {};
template<typename T, typename ... Ts>
void doSomething(T one, Ts...two){
if constexpr ( std::is_same_v<T, MyClassOne> )
std::cout << "im one" << std::endl;
else if constexpr ( std::is_same_v<T, MyClassTwo> )
std::cout <<"im two" << std::endl;
else
static_assert(false, "Only MyClassOne and MyClassTwo are permitted first arguments.");
}
int
main(int argc, char **argv) {
MyClassOne one;
MyClassTwo two;
doSomething(one, 1.5, two);
doSomething(two, 'c', one);
std::vector<MyClassOne> onesVector;
doSomething(onesVector, 1.0);
}
std::is_same_v<A,B>
results in atrue
value if the types A
and B
are the same. This answers your question "if parameter one is MyClass_one it should print "im one" if its MyClass_two it should print "im two".", and fails at compile time if the first argument is any type different than etither myClassOne
or myClassTwo
.
Edit: added a static_assert
that makes sure the compilation fails if the first argument is anything else except MyClassOne
or MyClassTwo
, as suggested by Justin Time in the comment.
without overloading
but overloading here make code simple:
template<typename ... Ts>
void doSomething(MyClass_one, Ts...two){
cout << "im one" << endl;
}
template<typename ... Ts>
void doSomething(MyClass_two, Ts...two){
cout <<"im two" << endl;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With