C++ 宏扩展不正确

问题描述 投票:0回答:1

COUNT_ARGS_IMPL 的代码是

#define COUNT_ARGS_IMPL(macro, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) _1

为什么 Visual Studio 编译器要在第一个参数中获取前一个宏的整个 var_args ?如果我尝试相同的代码但不嵌套它工作正常。它通常应该返回

macro##N
,但我在测试时这样做了,但它没有意义。

我进行了测试,没有将宏名称传递给计数参数,也没有在着色器程序宏运行之前预先计算计数,但问题仍然存在。

before replacement after replacement

如果你想要整个文件,就是这个。

#pragma once
#define GLAD_GL_IMPLEMENTATION
#include <glad/glad.h>
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <linmath.h>

static std::string readShader(const char const* location)
{
    char fileName[256] = "shaders\\";
    strcat_s(fileName, location);
    std::ifstream stream(fileName);

    if (!stream)
    {
        std::cerr << "Failed to open file: " << fileName << std::endl;
        return "";
    }

    std::stringstream buffer;

    buffer << stream.rdbuf();

    stream.close();
    return buffer.str();
}
static GLuint create_shader(const char const* location, int shaderType)
{
    std::string shaderText = readShader(location);
    const char* cShaderText = shaderText.c_str();

    const GLuint shader = glCreateShader(shaderType);
    glShaderSource(shader, 1, &cShaderText, NULL);
    glCompileShader(shader);

    GLint infoLength = 0;
    char* infoLogBuffer;

    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLength);
    if (infoLength > 1)
    {
        infoLogBuffer = (char*)malloc(infoLength);
        glGetShaderInfoLog(shader, infoLength, NULL, infoLogBuffer);
        std::cout << infoLogBuffer << std::endl;
        free(infoLogBuffer);
    }
    return shader;
}

int EndsWith(const char* str, const char* suffix)
{
    if (!str || !suffix)
        return 0;
    size_t lenstr = strlen(str);
    size_t lensuffix = strlen(suffix);
    if (lensuffix > lenstr)
        return 0;
    return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
}
#define str(x) #x

#define shader_prop(prop, type, element) \
GLint prop##_location; \
///##* program.##prop##_location - glGet##element##Location(program.shader, #prop);*##/

#define shader_uniform(prop, type) (prop, type, Uniform)
#define shader_attribute(prop, type) (prop, type, Attrib)

struct ShaderProgramShader {
    const char* path;
    int type;
};

#define generic_shader(path, type, extension) ShaderProgramShader {str(path.extension), type}

#define vert_shader(path) generic_shader(path, GL_VERTEX_SHADER, vert)
#define frag_shader(path) generic_shader(path, GL_FRAGMENT_SHADER, frag)

#define UNPAREN(...) __VA_ARGS__

#define COUNT_ARGS_IMPL(macro, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, N, ...) _1
#define COUNT_ARGS(macro,...) COUNT_ARGS_IMPL(macro, __VA_ARGS__, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define COUNT_LIST3(macro, ...) COUNT_ARGS(macro, __VA_ARGS__)
#define COUNT_LIST2(macro, ...) COUNT_LIST3(macro, __VA_ARGS__)
#define COUNT_LIST(macro, list) COUNT_LIST2(macro, UNPAREN list)

#define prop_attrib_define_p(name, type, element) type name;
#define prop_attrib_define_0(name, type, element)
#define prop_attrib_define_1(v1) prop_attrib_define_p v1
#define prop_attrib_define_2(v1, v2) prop_attrib_define_p v1 prop_attrib_define_1 (v2)
#define prop_attrib_define_3(v1, ...) prop_attrib_define_p v1 prop_attrib_define_2 (__VA_ARGS__)
#define prop_attrib_define_4(v1, ...) prop_attrib_define_p v1 prop_attrib_define_3 (__VA_ARGS__)
#define prop_attrib_define_5(v1, ...) prop_attrib_define_p v1 prop_attrib_define_4 (__VA_ARGS__)
#define prop_attrib_define_6(v1, ...) prop_attrib_define_p v1 prop_attrib_define_5 (__VA_ARGS__)
#define prop_attrib_define_7(v1, ...) prop_attrib_define_p v1 prop_attrib_define_6 (__VA_ARGS__)
#define prop_attrib_define_8(v1, ...) prop_attrib_define_p v1 prop_attrib_define_7 (__VA_ARGS__)
#define prop_attrib_define_9(v1, ...) prop_attrib_define_p v1 prop_attrib_define_8 (__VA_ARGS__)
#define prop_attrib_define_10(v1, ...) prop_attrib_define_p v1 prop_attrib_define_9 (__VA_ARGS__)

#define prop_location_define_p(name, type, element) GLint name##_location;
#define prop_location_define_0(name, type, element)
#define prop_location_define_1(v1) prop_location_define_p v1
#define prop_location_define_2(v1, v2) prop_location_define_p v1 prop_location_define_1 (v2)
#define prop_location_define_3(v1, ...) prop_location_define_p v1 prop_location_define_2 (__VA_ARGS__)
#define prop_location_define_4(v1, ...) prop_location_define_p v1 prop_location_define_3 (__VA_ARGS__)
#define prop_location_define_5(v1, ...) prop_location_define_p v1 prop_location_define_4 (__VA_ARGS__)
#define prop_location_define_6(v1, ...) prop_location_define_p v1 prop_location_define_5 (__VA_ARGS__)
#define prop_location_define_7(v1, ...) prop_location_define_p v1 prop_location_define_6 (__VA_ARGS__)
#define prop_location_define_8(v1, ...) prop_location_define_p v1 prop_location_define_7 (__VA_ARGS__)
#define prop_location_define_9(v1, ...) prop_location_define_p v1 prop_location_define_8 (__VA_ARGS__)
#define prop_location_define_10(v1, ...) prop_location_define_p v1 prop_location_define_9 (__VA_ARGS__)

#define prop_location_assign_p(name, type, element) program.name##_location = glGet##element##Location(program.shader, #name);
#define prop_location_assign_0(name, type, element)
#define prop_location_assign_1(v1) prop_location_assign_p v1
#define prop_location_assign_2(v1, v2) prop_location_assign_p v1 prop_location_assign_1 (v2)
#define prop_location_assign_3(v1, ...) prop_location_assign_p v1 prop_location_assign_2 (__VA_ARGS__)
#define prop_location_assign_4(v1, ...) prop_location_assign_p v1 prop_location_assign_3 (__VA_ARGS__)
#define prop_location_assign_5(v1, ...) prop_location_assign_p v1 prop_location_assign_4 (__VA_ARGS__)
#define prop_location_assign_6(v1, ...) prop_location_assign_p v1 prop_location_assign_5 (__VA_ARGS__)
#define prop_location_assign_7(v1, ...) prop_location_assign_p v1 prop_location_assign_6 (__VA_ARGS__)
#define prop_location_assign_8(v1, ...) prop_location_assign_p v1 prop_location_assign_7 (__VA_ARGS__)
#define prop_location_assign_9(v1, ...) prop_location_assign_p v1 prop_location_assign_8 (__VA_ARGS__)
#define prop_location_assign_10(v1, ...) prop_location_assign_p v1 prop_location_assign_9 (__VA_ARGS__)

#define prop_uniform_assign_float(shader_name, name) shader_name##_set_##name(shader_name##ShaderProgram& program, float value) { glUniform1f(program.name##_location, value); }
#define prop_uniform_assign_vec3(shader_name, name) shader_name##_set_##name(shader_name##ShaderProgram& program, vec3 value) { glUniform3fv(program.name##_location, 1, value); }
#define prop_uniform_assign_mat4x4(shader_name, name) shader_name##_set_##name(shader_name##ShaderProgram& program, mat4x4 value) { glUniform4fv(program.name##_location, 1, GL_FALSE, (const GLfloat*)value); }

#define prop_uniform_assign_p(shader_name, name, type, element) prop_uniform_assign_##type(shader_name, name)
#define prop_uniform_assign_0(shader_name, name, type, element)
#define prop_uniform_assign_1(shader_name, v1) prop_uniform_assign_p (shader_name, UNPAREN v1 )
#define prop_uniform_assign_2(shader_name, v1, v2) prop_uniform_assign_p (shader_name, UNPAREN v1) prop_uniform_assign_1 (shader_name, v2)
#define prop_uniform_assign_3(shader_name, v1, ...) prop_uniform_assign_p (shader_name, UNPAREN v1) prop_uniform_assign_2 (shader_name, __VA_ARGS__)
#define prop_uniform_assign_4(shader_name, v1, ...) prop_uniform_assign_p (shader_name, UNPAREN v1) prop_uniform_assign_3 (shader_name, __VA_ARGS__)
#define prop_uniform_assign_5(shader_name, v1, ...) prop_uniform_assign_p (shader_name, UNPAREN v1) prop_uniform_assign_4 (shader_name, __VA_ARGS__)
#define prop_uniform_assign_6(shader_name, v1, ...) prop_uniform_assign_p (shader_name, UNPAREN v1) prop_uniform_assign_5 (shader_name, __VA_ARGS__)
#define prop_uniform_assign_7(shader_name, v1, ...) prop_uniform_assign_p (shader_name, UNPAREN v1) prop_uniform_assign_6 (shader_name, __VA_ARGS__)
#define prop_uniform_assign_8(shader_name, v1, ...) prop_uniform_assign_p (shader_name, UNPAREN v1) prop_uniform_assign_7 (shader_name, __VA_ARGS__)
#define prop_uniform_assign_9(shader_name, v1, ...) prop_uniform_assign_p (shader_name, UNPAREN v1) prop_uniform_assign_8 (shader_name, __VA_ARGS__)
#define prop_uniform_assign_10(shader_name, v1, ...) prop_uniform_assign_p (shader_name, UNPAREN v1) prop_uniform_assign_9 (shader_name, __VA_ARGS__)


#define shader_program(shader_name, shaders, attributes, uniforms) \
typedef struct shader_name##ShaderProgram {\
    GLuint shader;\
    COUNT_LIST(prop_location_define_, attributes)\
    COUNT_LIST(prop_location_define_, uniforms)\
} shader_name##ShaderProgram;\
typedef struct shader_name##Vertex {\
    COUNT_ARGS(prop_attrib_define_, UNPAREN attributes) attributes\
} shader_name##Vertex;\
static void create_##shader_name##ShaderProgram(shader_name##ShaderProgram& program)\
{\
    ShaderProgramShader shader_list[] UNPAREN shaders;\
    GLuint created_shaders[sizeof(shader_list) / sizeof(ShaderProgramShader)];\
    for(int i = 0; i < sizeof(shader_list) / sizeof(ShaderProgramShader); i++) {\
        created_shaders[i] = create_shader(shader_list[i].path, shader_list[i].type);\
    }\
    program.shader = glCreateProgram();\
    \
    glLinkProgram(program.shader);\
    \
    for(int i = 0; i < sizeof(shader_list) / sizeof(ShaderProgramShader); i++) {\
        glDeleteShader(created_shaders[i]);\
    }\
    \
    COUNT_ARGS(prop_location_assign_, UNPAREN attributes) attributes\
    COUNT_ARGS(prop_location_assign_, UNPAREN uniforms) uniforms\
}\
COUNT_ARGS(prop_uniform_assign_, UNPAREN uniforms) (shader_name, UNPAREN uniforms)\


//#define shader_program(shader_name, uniforms) \
COUNT_ARGS(prop_uniform_assign_, UNPAREN uniforms) (shader_name, UNPAREN uniforms)\

shader_program(Ocean, ({vert_shader(ocean)}), (0), (shader_uniform(mv, mat4x4), shader_uniform(perspective, mat4x4), 0, 2, 3))
c++ macros
1个回答
0
投票

按照 HolyBlackCat 的建议,通过启用 /Zc:preprocessor 解决了该问题。

© www.soinside.com 2019 - 2024. All rights reserved.