Reputation: 698
I have a number of classes in my project that acts as a message. and also have a template function that takes a class type and do some work with it.
template <typename T>
static int SendBroadcastMsg(T msg)
{
//....do something
return 0; //return an int result once finished.
}
in my main, I have a bunch of messages sent using this template. but I want to limit the template arguments to only Message
and AnotherMsg
types.
SendBroadcastMsg<Message>(1); //should be valid
SendBroadcastMsg<AnotherMsg>({ true, 2 }); //should be valid
SendBroadcastMsg<NotAMsg>(1);//shoud NOT be valid.
SendBroadcastMsg<NotAMsg>({ false, 1 });// should NOT be valid.
I found some answers here but I can't seem to get it working. I'm suspecting its perhaps due to the constructors of these classes have parameters in it but I'm not sure how to deal with it. Any help would be appreciated.
Full code :
#include <iostream>
#include <memory>
#include <vector>
struct Message
{
Message( const int val) : Val(val) {}
int Val;
};
struct AnotherMsg
{
AnotherMsg( const bool con, int val) : Cond(con), Val(val){}
bool Cond;
int Val;
};
struct NotAMsg
{
NotAMsg(const int val) : Val(val), Cond(false){}
NotAMsg(const bool con, int val) : Cond(con), Val(val){}
bool Cond;
int Val;
};
//template function wrapper.
template <typename T>
static int SendBroadcastMsg(T msg)
{
//....do something
return 0; //return an int result once finished.
}
template <typename T>
constexpr bool is_ValidMsg()
{
return std::is_same<T, Message>(const int) || std::is_same<T, AnotherMsg>(const bool, int);
}
template <typename T>
using common_byfunc = typename std::conditional<is_ValidMsg<T>(), NotAMsg, T>::type;
static_assert(std::is_same <common_byfunc<Message>, NotAMsg>(), "");
static_assert(std::is_same <common_byfunc<AnotherMsg>, NotAMsg>(), "");
int main()
{
SendBroadcastMsg<Message>(1);
SendBroadcastMsg<AnotherMsg>({ true, 2 });
SendBroadcastMsg<NotAMsg>(1);//shoud not be valid.
SendBroadcastMsg<NotAMsg>({ false, 1 });// should not be valid.
return 0;
}
Upvotes: 1
Views: 91
Reputation: 66240
The correct syntax (a possible correct syntax) is
template <typename T>
constexpr bool is_ValidMsg()
{
return std::is_same<T, Message>::value || std::is_same<T, AnotherMsg>::value;
}
I mean... I don't know what do you mean with
std::is_same<T, Message>(const int)
and
std::is_same<T, AnotherMsg>(const bool, int)
but they are wrong.
If you want avoid that SendBroadcastMsg()
is compiled with non message types, you can use is_ValidMsg()
to SFINAE enable/disable it.
There are many ways; by example
template <typename T>
static std::enable_if_t<is_ValidMsg<T>(), int> SendBroadcastMsg(T msg)
{
//....do something
return 0; //return an int result once finished.
}
But remember to define is_ValidMsg()
before SendBroadcasMsg()
Another possible solution pass through the use of is_ValidMsg()
in a simple static_assert()
inside SendBroadcastMsg()
template <typename T>
static int SendBroadcastMsg(T msg)
{
static_assert( is_ValidMsg<T>(), "!" );
//....do something
return 0; //return an int result once finished.
}
Upvotes: 1