首页 > 解决方案 > 将模板参数限制为仅具有不同构造函数签名的类集

问题描述

我的项目中有许多类充当消息。并且还有一个模板函数,它接受一个类类型并使用它做一些工作。

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

在我的主要,我有一堆使用这个模板发送的消息。但我想将模板参数限制为仅MessageAnotherMsg类型。

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

标签: c++c++11templatesc++14sfinae

解决方案


正确的语法(可能的正确语法)是

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

推荐阅读