Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;验证模板类型的可调用签名_C++_Templates - Fatal编程技术网

C++ C++;验证模板类型的可调用签名

C++ C++;验证模板类型的可调用签名,c++,templates,C++,Templates,假设我有这样一个通用函数: template<typename TFunc> void templFunc(TFunc func) { func(3, 6); } 模板 无效模板函数(TFunc函数){ func(3,6); } 在编译时是否有任何方法可以验证TFunc的签名,而不管它是std::函数还是lambda或任何类型的函数引用。我只想确保TFunc的签名无效(int,int)或与静态断言类似,以便生成非垃圾错误消息。您可以使用: template<type

假设我有这样一个通用函数:

template<typename TFunc>
void templFunc(TFunc func) {
    func(3, 6);
}
模板
无效模板函数(TFunc函数){
func(3,6);
}
在编译时是否有任何方法可以验证TFunc的签名,而不管它是std::函数还是lambda或任何类型的函数引用。我只想确保TFunc的签名无效(int,int)或与静态断言类似,以便生成非垃圾错误消息。

您可以使用:

template<typename TFunc>
void templFunc(TFunc func) {
   static_assert(std::is_void<decltype(func(0,0))>::value,
                 "Bad template argument. The return type is not void");
   func(3, 6);
}

类似的东西在使用SFINAE时可以使用(仅当您基于模板参数进行断言时;不确定原因,我认为这将是最有趣的部分:):

#包括
模板
typename std::enable_if::type templafunc(TFunc func)
{
func(3,6);
}
模板
typename std::enable_if::type,void>::value>::type templafunc(TFunc func)
{
静态断言(std::is_same::value,“error;invalid function”);
}
自动a=[](int,int){};
自动b=[](int x,int y){返回x+y;};
int main()
{
坦普尔Func(b);
返回0;
}

所以我摆弄了一些type\u traits的东西,我认为我有一些东西可以验证整个签名,而不仅仅是返回值,并且允许您创建易于阅读的静态断言,而不是签名不匹配时难以辨认的模板错误。这是一个糟糕的解决方案吗

#include <functional>

template<typename, typename, typename = void>
struct is_signature : std::false_type {};

template<typename TFunc, typename Ret, typename... Args>
struct is_signature<TFunc, Ret(Args...),
        typename std::enable_if<
            std::is_convertible<
                TFunc,
                std::function<Ret(Args...)>
            >::value
        >::type
    > : public std::true_type
    {};

// works on both functions and lambda's
void blah(int, int) {
}

template<typename TFunc>
void templFunc(TFunc func) {
    static_assert(is_signature<TFunc, void(int, int)>::value, "Not gonna work! more info follows:");
    func(3, 6);
}

int main() {
    auto b = [](int, int) -> void {
    };

    auto c = [](int) -> void {
    };

    static_assert(is_signature<decltype(b), void(int, int)>::value, "b convertible to a std::function<void(int, int), so this checks out!");
    static_assert(is_signature<decltype(b), void(int)>::value, "b not convertible to a std::function<void(int)>, so this will error in compilation.");
    static_assert(is_signature<decltype(blah), void(int, int)>::value, "blah convertible to a std::function<void(int, int), so this checks out!");
    static_assert(is_signature<decltype(blah), void(int)>::value, "blah not convertible to a std::function<void(int)>, so this will error in compilation.");

    templFunc(b); // <- ok
    templFunc(c); // <- static assertion : not gonna work!
    return 0;
}
#包括
模板
结构是_签名:std::false_类型{};
模板
结构是_签名::值
>::类型
>:public std::true\u类型
{};
//对函数和lambda都有效
虚空废话(int,int){
}
模板
无效模板函数(TFunc函数){
静态_断言(是_签名::值,“不起作用!更多信息如下:”;
func(3,6);
}
int main(){
自动b=[](int,int)->void{
};
自动c=[](int)->void{
};

静态断言(即签名::值,“根据标准
dcl.dcl
,b可转换为标准::函数”,在静态断言声明中,常量表达式应为常量表达式(5.19),可在上下文中转换为bool。。。"…因此,我假设当
static_assert
表达式中不包含模板依赖项时,可以在函数模板的上下文之外对其求值,这样它就不依赖于函数模板是否为重载解析求值了?…因此它总是被求值的?这将返回函数的
true
lambda函数定义为
autoa=[](长,int){}
@user2296177:是的,还有
double
或任何其他可以隐式转换为
int
的东西。它也只在返回类型不正确时给出友好的错误消息,而不是在参数的数量或类型错误时……你确定这工作正常吗?
是\u签名::value==true
for
auto a=[](int,int){return 0;};
也不会为
自动a=[](int,char){};
@user2296177和@mkal-你说得对。像
自动b=[](int,int){return 0;}这样的东西怎么可能呢
被分配到
std::function
。当我写
std::function meh=b;
时,我没有得到错误,但是这些类型如何转换?查看缩小转换范围。如果lambda不是必需的,那么您可以使用
静态断言(std::is_same::value,“error”);
另请参阅
#include <type_traits>

template<typename TFunc>
typename std::enable_if<std::is_same<typename std::result_of<TFunc(int, int)>::type, void>::value >::type templFunc(TFunc func)
{
  func(3, 6);
}

template<typename TFunc>
typename std::enable_if<!std::is_same<typename std::result_of<TFunc(int, int)>::type, void>::value >::type templFunc(TFunc func)
{
  static_assert(std::is_same<typename std::result_of<TFunc(int, int)>::type, void>::value, "error; invalid function");
}

auto a = [](int, int) {};
auto b = [](int x, int y) { return x + y; };

int main()
{
    templFunc(b);
    return 0;
}
#include <functional>

template<typename, typename, typename = void>
struct is_signature : std::false_type {};

template<typename TFunc, typename Ret, typename... Args>
struct is_signature<TFunc, Ret(Args...),
        typename std::enable_if<
            std::is_convertible<
                TFunc,
                std::function<Ret(Args...)>
            >::value
        >::type
    > : public std::true_type
    {};

// works on both functions and lambda's
void blah(int, int) {
}

template<typename TFunc>
void templFunc(TFunc func) {
    static_assert(is_signature<TFunc, void(int, int)>::value, "Not gonna work! more info follows:");
    func(3, 6);
}

int main() {
    auto b = [](int, int) -> void {
    };

    auto c = [](int) -> void {
    };

    static_assert(is_signature<decltype(b), void(int, int)>::value, "b convertible to a std::function<void(int, int), so this checks out!");
    static_assert(is_signature<decltype(b), void(int)>::value, "b not convertible to a std::function<void(int)>, so this will error in compilation.");
    static_assert(is_signature<decltype(blah), void(int, int)>::value, "blah convertible to a std::function<void(int, int), so this checks out!");
    static_assert(is_signature<decltype(blah), void(int)>::value, "blah not convertible to a std::function<void(int)>, so this will error in compilation.");

    templFunc(b); // <- ok
    templFunc(c); // <- static assertion : not gonna work!
    return 0;
}