首页 \ 问答 \ 如何从可变参数宏正确调用可变参数模板函数?(How to correctly call a variadic template function from a variadic macro?)

如何从可变参数宏正确调用可变参数模板函数?(How to correctly call a variadic template function from a variadic macro?)

好的,首先,我将提供我正在问我的问题的代码。

EX_Factory.h

#ifndef EX_FACTORY_H
#define EX_FACTORY_H

#include <string>
#include <map>
#include "Base.h"

struct EX_Factory{
    template<class U, typename... Args>
    static void registerC(const std::string &name){
        registry<Args...>[name] = &create<U>;
    }
    template<typename... Args>
    static Base * createObject(const std::string &key, Args... args){
        auto it = registry<Args...>.find(key);
        if(it == registry<Args...>.end()) return nullptr;
        return it->second(args...);
    }
    private:
        EX_Factory() = delete;
        template<typename... Args>
        static std::map<std::string, Base*(*)(Args...)> registry;

        template<class U, typename... Args>
        static Base* create(Args... args){
            return new U(args...);
        }
};

template<typename... Args>
std::map<std::string, Base*(*)(Args...)> EX_Factory::registry;

template<typename U, typename... Args>
struct MiddleMan{
    MiddleMan(const std::string &name){
        EX_Factory::registerC<U,Args...>(name);
    }
};
  #define REGISTER_MACRO(NAME, TYPE, ...)\ // Updated the macro here
    static MiddleMan<TYPE, ##__VA_ARGS__> mm_##TYPE(#NAME);

#endif

上面的代码是我的Factory Design Pattern类的头文件。 它允许此类的用户为具有不同参数的Base类派生的对象注册构造函数。

好吧,快速解释为什么我使用__VA_ARGS__ vs ## __ VA_ARGS__,原因是,寄存器模板函数中的模板类型U总会至少有一个参数传递给宏。

我想要做的是构造一个预处理器宏 REGISTER_MACRO ,以在运行时之前注册派生类。 如何正确地从可变参数宏调用变量模板函数

测试或main.cpp

#include "EX_Factory_1.h"
#include <iostream>

using namespace std;

struct derived_1 : public Base{
    derived_1(int i, int j, float f){
        cout << "Derived 1:\t" << i * j + f << endl;
    }
};
REGISTER_MACRO(name_1, derived_1, int,int,float);
struct derived_2 : public Base{
    derived_2(int i, int j){
        cout << "Derived 2:\t" << i + j << endl;
    }
};
REGISTER_MACRO(name_2, derived_2, int,int);

int main(){ // Program segfaults before entering main
    derived_1 * d_1 = static_cast<derived_1*>(EX_Factory::createObject<int, int, float>("name_1", 8, 8, 3.0));
    if(d_1 == nullptr) cout << "Why is it null?" << endl;
    else{
        delete d_1;
    }
    return 0;
}

我在尝试编译上述代码时收到的错误: 请参阅下面的编辑

In file included from test.cpp:1:0:
EX_Factory.h:39:38: error: expected constructor, destructor, or type conversion before ‘(’ token
    EX_Factory::registerC<__VA_ARGS__>(NAME);
                                      ^
test.cpp:11:1: note: in expansion of macro ‘REGISTER_MACRO’
 REGISTER_MACRO("derived_1",derived_1,int,int,float)
 ^~~~~~~~~~~~~~
EX_Factory.h:39:38: error: expected constructor, destructor, or type conversion before ‘(’ token
    EX_Factory::registerC<__VA_ARGS__>(NAME);
                                      ^
test.cpp:17:1: note: in expansion of macro ‘REGISTER_MACRO’
 REGISTER_MACRO("derived_2",derived_2,int,int)

我使用的是g ++ 6.3编译器,因此默认情况下,它在Ubuntu 16.04环境中使用C ++ 14标准进行编译。

我找到的潜在解决方案,但不适合我的问题:

有没有办法定义可变参数模板宏

使用可变参数宏或模板来实现一组函数

潜在的解决方案但无法解释其解决方案:

如何使用variadic模板与variadic宏? 我没有使用QT,而且我使用的是完全支持的C ++ 11编译器。

编辑

我现在知道为什么我的文件不会编译,但我不知道如何处理创建一个对象来为自己调用该方法。 我添加了一个中间人类,MiddleMan,并将静态registerC类的调用添加到其构造函数中,并修改了我的宏以创建对此类的静态引用。 这允许我的程序编译,但它使用此方法进行了段错误。 您现在将看到上面提到的反思。

在我对这个问题的回答中,我正在使用main.cpp测试这个类和宏。


Alright, first things first, I will be providing the code I am asking my question for.

EX_Factory.h

#ifndef EX_FACTORY_H
#define EX_FACTORY_H

#include <string>
#include <map>
#include "Base.h"

struct EX_Factory{
    template<class U, typename... Args>
    static void registerC(const std::string &name){
        registry<Args...>[name] = &create<U>;
    }
    template<typename... Args>
    static Base * createObject(const std::string &key, Args... args){
        auto it = registry<Args...>.find(key);
        if(it == registry<Args...>.end()) return nullptr;
        return it->second(args...);
    }
    private:
        EX_Factory() = delete;
        template<typename... Args>
        static std::map<std::string, Base*(*)(Args...)> registry;

        template<class U, typename... Args>
        static Base* create(Args... args){
            return new U(args...);
        }
};

template<typename... Args>
std::map<std::string, Base*(*)(Args...)> EX_Factory::registry;

template<typename U, typename... Args>
struct MiddleMan{
    MiddleMan(const std::string &name){
        EX_Factory::registerC<U,Args...>(name);
    }
};
  #define REGISTER_MACRO(NAME, TYPE, ...)\ // Updated the macro here
    static MiddleMan<TYPE, ##__VA_ARGS__> mm_##TYPE(#NAME);

#endif

The code above is a header file for my Factory Design Pattern class. It allows the user of this class to register constructors for objects derived from the Base class with varying arguments.

Alright, quick explanation for why I am using __VA_ARGS__ vs ##__VA_ARGS__, the reason for this is, there will always be at least 1 argument, the template type U in the registerC template function, passed into the macro.

What I am trying to do is construct a preprocessor macro, REGISTER_MACRO , to register derived classes before runtime. How do I call a Variadic Template Function from a Variadic Macro correctly?

Tests or main.cpp

#include "EX_Factory_1.h"
#include <iostream>

using namespace std;

struct derived_1 : public Base{
    derived_1(int i, int j, float f){
        cout << "Derived 1:\t" << i * j + f << endl;
    }
};
REGISTER_MACRO(name_1, derived_1, int,int,float);
struct derived_2 : public Base{
    derived_2(int i, int j){
        cout << "Derived 2:\t" << i + j << endl;
    }
};
REGISTER_MACRO(name_2, derived_2, int,int);

int main(){ // Program segfaults before entering main
    derived_1 * d_1 = static_cast<derived_1*>(EX_Factory::createObject<int, int, float>("name_1", 8, 8, 3.0));
    if(d_1 == nullptr) cout << "Why is it null?" << endl;
    else{
        delete d_1;
    }
    return 0;
}

The errors I am receiving from trying to compile the above code: See Edit below

In file included from test.cpp:1:0:
EX_Factory.h:39:38: error: expected constructor, destructor, or type conversion before ‘(’ token
    EX_Factory::registerC<__VA_ARGS__>(NAME);
                                      ^
test.cpp:11:1: note: in expansion of macro ‘REGISTER_MACRO’
 REGISTER_MACRO("derived_1",derived_1,int,int,float)
 ^~~~~~~~~~~~~~
EX_Factory.h:39:38: error: expected constructor, destructor, or type conversion before ‘(’ token
    EX_Factory::registerC<__VA_ARGS__>(NAME);
                                      ^
test.cpp:17:1: note: in expansion of macro ‘REGISTER_MACRO’
 REGISTER_MACRO("derived_2",derived_2,int,int)

I am using the g++ 6.3 compiler, so by default, it compiles with C++14 standards in an Ubuntu 16.04 environment.

Potential solutions I've found, but don't fit my problem:

Is there a way to define variadic template macro

Using variadic macros or templates to implement a set of functions

Potential Solution but could not interpret its solution:

How to use variadic template with variadic macro ? I'm not using QT, and I am using a fully supported C++11 compiler.

Edit

I now know why my file will not compile, but I do not know how to handle creating an object to call the method for myself. I added a middle man class, MiddleMan, and added a call to the static registerC class to its constructor and modified my macro to create static references to this class. This allows my program to compile, but it segfaults with this method. You will see the mentioned reflections above now.

I am testing this class and macro out with my main.cpp in my answer to this question.


原文:https://stackoverflow.com/questions/43946698
更新时间:2024-03-23 11:03

最满意答案

只需使整个布局灵活。 然后,您可以使用宽度调整图像大小:90%; (或您喜欢的任何值),或使用max-width:90%; 如果你不想让图像升级。

使用媒体查询或css无法逐步调整文本大小,但你真的不应该这样做。 窗口较小的人将无法阅读文本,而大屏幕的人将不得不坐下来,因为文本很大。 更不用说使用手机的人了。


Just make the entire layout flexible. You could then resize the images using width: 90%; (or any value you like), Or use max-width:90%; if you don't want the image to upscale.

Gradually resizing the text is not possible using media queries or css, but you really shouldn't do that. People with smaller windows wouldn't be able to read the text, and people with big screens will have to sit back because the text is to big. Not to mention people using a mobile phone.

相关问答

更多
  • 用逗号分隔它们: @media only print, only screen and (max-device-width: 480px) 参见规范 ,特别是示例VI(重点添加): 可以在媒体查询列表中组合多个媒体查询。 以逗号分隔的媒体查询列表。 如果逗号分隔列表中的一个或多个媒体查询为true,则整个列表为true,否则为false。 在媒体查询语法中, 逗号表示逻辑或 ,而'和'关键字表示逻辑AND。 我怀疑第二个only需要的,所以你可以做: @media only print, screen a ...
  • 您不需要JS为MediaQueries工作或检测屏幕大小/视图端口。 此外,您不需要刷新浏览器以查看MediaQuery的结果。 看看这篇文章的详细信息和'如何'使用MediaQueries: http://www.smashingmagazine.com/2010/07/19/how-to-use-css3-media-queries-to-create-a-mobile-version-of-your-website/ 可能最简单的方法是在HTML的头部提供单独的MediaQueries:
  • .class { /* default style */ } @media (min-width: 100px) and (max-width: 480px) { .class { /* style */ } } @media (min-width: 481px) and (max-width: 600px) { .class { /* style */ } } @media (min-width: 601px) and (max-width: 800px) { .class { /* styl ...
  • 您的测试证明它应该如何工作 。 在您的示例中,当浏览器的宽度小于960px 且小于700px时,两个查询都将被视为true。 这是按预期工作的,事实上,我是如何在多个站点上实现响应式设计的,每个查询都是一个新的断点,表明事物如何优雅地降级为小型。 Your tests prove true how it should work. In your example, when the width of the browser is less than 960px and less than 700px, bot ...
  • 我在这里给出的完全相同的答案可以应用于您的问题: 以下是您应该如何使用媒体查询 : 请记住使用您喜欢/需要的尺寸。 以下仅用于演示目的。 使用max-width 非移动第一种方法 : /*========== Non-Mobile First Method ==========*/ @media only screen and (max-width: 960px) { /*your CSS Rules*/ } @media only screen and ...
  • SASS将对嵌套属性进行排序,以使媒体查询持续。 以下是一些发生的事例: SCSS body { background: #000000; //black @media (max-width: 500px) { background: #990000; //red } background: #000099; //blue @media (max-width: 300px) { background: #009900; //g ...
  • 不,他们不会。 这是因为device-width与width 。 如果您的媒体查询只有width它们的行为会相同,但是当您引入device-width您会得到不同的结果。 有关详细信息,请参阅我对此问题的回复: 针对iPhone iPad的CSS样式表无法正常工作 No, they will not. This is because device-width is not the same as width. If your media query has just width they'll behave ...
  • 尝试切换到最小宽度,看看是否能解决您的问题。 或者,如果这不能解决它,你将不得不尝试这样的事情: @media (min-width: 1500px) and (max-width: 2499px) { .mydiv{position:absolute; top:0; left:0; padding-left: 920px;padding-top: 160px; } there was an extra bracket before the last media query !! Sorry fo ...
  • 只需使整个布局灵活。 然后,您可以使用宽度调整图像大小:90%; (或您喜欢的任何值),或使用max-width:90%; 如果你不想让图像升级。 使用媒体查询或css无法逐步调整文本大小,但你真的不应该这样做。 窗口较小的人将无法阅读文本,而大屏幕的人将不得不坐下来,因为文本很大。 更不用说使用手机的人了。 Just make the entire layout flexible. You could then resize the images using width: 90%; (or any val ...
  • 如果有人提出同样的问题,我解决了在我的HTML代码的某些方面添加这些代码的安静:

相关文章

更多

最新问答

更多
  • h2元素推动其他h2和div。(h2 element pushing other h2 and div down. two divs, two headers, and they're wrapped within a parent div)
  • 创建一个功能(Create a function)
  • 我投了份简历,是电脑编程方面的学徒,面试时说要培训三个月,前面
  • PDO语句不显示获取的结果(PDOstatement not displaying fetched results)
  • Qt冻结循环的原因?(Qt freezing cause of the loop?)
  • TableView重复youtube-api结果(TableView Repeating youtube-api result)
  • 如何使用自由职业者帐户登录我的php网站?(How can I login into my php website using freelancer account? [closed])
  • SQL Server 2014版本支持的最大数据库数(Maximum number of databases supported by SQL Server 2014 editions)
  • 我如何获得DynamicJasper 3.1.2(或更高版本)的Maven仓库?(How do I get the maven repository for DynamicJasper 3.1.2 (or higher)?)
  • 以编程方式创建UITableView(Creating a UITableView Programmatically)
  • 如何打破按钮上的生命周期循环(How to break do-while loop on button)
  • C#使用EF访问MVC上的部分类的自定义属性(C# access custom attributes of a partial class on MVC with EF)
  • 如何获得facebook app的publish_stream权限?(How to get publish_stream permissions for facebook app?)
  • 如何防止调用冗余函数的postgres视图(how to prevent postgres views calling redundant functions)
  • Sql Server在欧洲获取当前日期时间(Sql Server get current date time in Europe)
  • 设置kotlin扩展名(Setting a kotlin extension)
  • 如何并排放置两个元件?(How to position two elements side by side?)
  • 如何在vim中启用python3?(How to enable python3 in vim?)
  • 在MySQL和/或多列中使用多个表用于Rails应用程序(Using multiple tables in MySQL and/or multiple columns for a Rails application)
  • 如何隐藏谷歌地图上的登录按钮?(How to hide the Sign in button from Google maps?)
  • Mysql左连接旋转90°表(Mysql Left join rotate 90° table)
  • dedecms如何安装?
  • 在哪儿学计算机最好?
  • 学php哪个的书 最好,本人菜鸟
  • 触摸时不要突出显示表格视图行(Do not highlight table view row when touched)
  • 如何覆盖错误堆栈getter(How to override Error stack getter)
  • 带有ImageMagick和许多图像的GIF动画(GIF animation with ImageMagick and many images)
  • USSD INTERFACE - > java web应用程序通信(USSD INTERFACE -> java web app communication)
  • 电脑高中毕业学习去哪里培训
  • 正则表达式验证SMTP响应(Regex to validate SMTP Responses)