Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.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++ 将函数引用传递到模板警告:忽略模板参数上的属性';func签名';_C++_Templates_C++17 - Fatal编程技术网

C++ 将函数引用传递到模板警告:忽略模板参数上的属性';func签名';

C++ 将函数引用传递到模板警告:忽略模板参数上的属性';func签名';,c++,templates,c++17,C++,Templates,C++17,我试图创建一个复合记录器,它将在编译时被选择和定义。 最初的实现是使用继承和VTable,这会造成一些开销,占用太多的代码,并且在运行时无效。这应该是简单化的,它基本上接受C++中定义的任何流,然后引用 yScript()/代码>函数,检查类型,然后让编译器生成适当的机器代码。 它的工作原理应该是这样的,但是我想问一下这个警告: $ g++ -std=c++17 template_types.cpp -o asd template_types.cpp: In function ‘int main

我试图创建一个复合记录器,它将在编译时被选择和定义。 最初的实现是使用继承和VTable,这会造成一些开销,占用太多的代码,并且在运行时无效。这应该是简单化的,它基本上接受C++中定义的任何流,然后引用<代码> yScript()/代码>函数,检查类型,然后让编译器生成适当的机器代码。 它的工作原理应该是这样的,但是我想问一下这个警告:

$ g++ -std=c++17 template_types.cpp -o asd
template_types.cpp: In function ‘int main(int, char**)’:
template_types.cpp:44:41: warning: ignoring attributes on template argument ‘void (&)(int, const char*, ...)’ [-Wignored-attributes]
44 |   logger<syslog_log_t, decltype(syslog)&> C(syslog);

如果检查系统头文件中的
syslog
函数声明,您将看到类似以下内容:

extern void syslog (int __pri, const char *__fmt, ...)
     __attribute__ ((__format__ (__printf__, 2, 3)));
在正常使用情况下,此属性用于将格式字符串与参数匹配。
您的编译器告诉您,它将无法在模板版本中执行这些检查

第二个问题是,当前代码基本上接受格式字符串,而不执行任何验证! 因此,如果您执行
C.log(“某些文本%s bla bla\n”,log_DEBUG),您可能会遇到很多麻烦(或者至少是未定义的行为)和编译器将无法警告您

您应该按照如下方式重写
log
方法的syslog分支,这是安全的,因为实际的格式字符串是“%s”,并且日志字符串是它的一个简单参数:

file(log_level, "%s", msg.c_str());

您可以将实际的
log
实现放在现在的标记类中,并使用

有了它,您的
记录器
可以被任何您想将新设备插入日志类的人使用。只需实现一个
log
函数,它就准备好了

它可能看起来像这样:

#include <syslog.h>

#include <fstream>
#include <iostream>
#include <sstream>

/* types of logger, now including implementations */

template<int prio>
struct syslog_log_t {
    static void log(const std::string& msg) {
        ::syslog(prio, "%s", msg.c_str());
    }
};

struct console_log_t {
    static void log(const std::string& msg) { std::cout << msg; }
};

struct file_log_t {
    // this can be instantiated just like any ofstream
    template<typename... Args>
    file_log_t(Args&&... f) : file(std::forward<Args>(f)...) {}

    // non-static here since we own an ofstream instance
    void log(const std::string& msg) { file << msg; }

private:
    std::ofstream file; // no dtor necessary - it'll close automatically
};

template<typename T>
class logger : public T {
public:
    template<typename... Args>
    explicit logger(Args&&... args) : T(std::forward<Args>(args)...) {}
};

// a common front to support streaming
template<typename T, typename U>
logger<T>& operator<<(logger<T>& l, U&& u) {
    std::stringstream ss;
    ss << std::forward<U>(u);
    l.log(ss.str());
    return l;
}

int main() {
    logger<file_log_t> A("text.txt", std::ios_base::app);
    A << "Hello\n";

    logger<console_log_t> B;
    B << "COUT\n";

    logger<syslog_log_t<0>> C;
    C << "SYSLOG\n";
}
#包括
#包括
#包括
#包括
/*记录器的类型,现在包括实现*/
模板
结构syslog\u log\t{
静态无效日志(const std::string和msg){
::syslog(prio,“%s”,msg.c_str());
}
};
结构控制台日志{

静态无效日志(const std::string和msg){std::cout So,如果我理解正确,我必须更改方法
log
的签名,以像syslog一样接受可变参数?并相应地更改实现?谢谢,但是警告仍然会弹出。恐怕您必须接受它或禁用警告。非常感谢,我将标记它相关:但是不要期望太高,答案是你不能,也就是说,你可以让你的代码工作,就像你做的那样,但是检查va_list参数的属性(在你的案例中的syslog中)不起作用。@AmirKirsh谢谢你。
#include <syslog.h>

#include <fstream>
#include <iostream>
#include <sstream>

/* types of logger, now including implementations */

template<int prio>
struct syslog_log_t {
    static void log(const std::string& msg) {
        ::syslog(prio, "%s", msg.c_str());
    }
};

struct console_log_t {
    static void log(const std::string& msg) { std::cout << msg; }
};

struct file_log_t {
    // this can be instantiated just like any ofstream
    template<typename... Args>
    file_log_t(Args&&... f) : file(std::forward<Args>(f)...) {}

    // non-static here since we own an ofstream instance
    void log(const std::string& msg) { file << msg; }

private:
    std::ofstream file; // no dtor necessary - it'll close automatically
};

template<typename T>
class logger : public T {
public:
    template<typename... Args>
    explicit logger(Args&&... args) : T(std::forward<Args>(args)...) {}
};

// a common front to support streaming
template<typename T, typename U>
logger<T>& operator<<(logger<T>& l, U&& u) {
    std::stringstream ss;
    ss << std::forward<U>(u);
    l.log(ss.str());
    return l;
}

int main() {
    logger<file_log_t> A("text.txt", std::ios_base::app);
    A << "Hello\n";

    logger<console_log_t> B;
    B << "COUT\n";

    logger<syslog_log_t<0>> C;
    C << "SYSLOG\n";
}