ограничение аргументов шаблона только набором классов, которые имеют различную сигнатуру конструктора - PullRequest
0 голосов
/ 25 октября 2018

В моем проекте есть несколько классов, которые действуют как сообщения.а также у меня есть шаблонная функция, которая принимает тип класса и выполняет с ним некоторую работу.

template <typename T>
static int SendBroadcastMsg(T msg)
{
    //....do something
    return 0; //return an int result once finished.
}

в моем основном, у меня есть куча сообщений, отправленных с использованием этого шаблона.но я хочу ограничить аргументы шаблона только типами Message и AnotherMsg.

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.

Я нашел несколько ответов здесь , но я не могу заставить его работать.Я подозреваю, что это возможно из-за того, что конструкторы этих классов содержат параметры, но я не знаю, как с этим справиться.Любая помощь будет оценена.

Полный код:

#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;
}

1 Ответ

0 голосов
/ 25 октября 2018

Правильный синтаксис (возможный правильный синтаксис):

template <typename T>
constexpr bool is_ValidMsg()
{
    return std::is_same<T, Message>::value || std::is_same<T, AnotherMsg>::value;
}

Я имею в виду ... Я не знаю, что вы имеете в виду с

std::is_same<T, Message>(const int)

и

std::is_same<T, AnotherMsg>(const bool, int)

, но они ошибочны.

Если вы хотите избежать компиляции SendBroadcastMsg() с сообщениями других типов, вы можете использовать is_ValidMsg() для включения / выключения SFINAE.

Есть много способов;например

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.
}

Но не забудьте определить is_ValidMsg() до SendBroadcasMsg()

Еще один возможный вариант решения - использование is_ValidMsg() в простом static_assert() внутри SendBroadcastMsg()

template <typename T>
static int SendBroadcastMsg(T msg)
{
   static_assert( is_ValidMsg<T>(), "!" );

    //....do something
    return 0; //return an int result once finished.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...