Jump to content
  • Advertisement
Sign in to follow this  
louie999

Problem with variable arguments

This topic is 1042 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Whenever I try to compile this files then it results in this error:

||=== Build: Debug in Game(compiler: GNU GCC Compiler) ===|

menuhandler.cpp||In member function 'void Gui::GuiHandler<C>::addGuiElem(...)':|
menuhandler.cpp|42|error: expected primary-expression before '...' token|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|

 

 
 
menuhandler.hpp
#pragma once

namespace Gui
{
    class GuiBase
    {
        public:
            float PosX;
            float PosY;
            float Width;
            float Height;
            void SetPos(float newX, float newY);
            void Move(float newX, float newY, float rate);
            sf::Text textDisplay;
            sf::Image imgDisplay;
    };

    class Button : public GuiBase
    {
        public:
            Button(float x, float y, float width, float height, sf::String text, sf::Font& font, unsigned int textSize);
            bool isClicked();
            bool isMouseIn();
            void SetText(sf::String newText);
    };
    template <class C>
    class GuiHandler
    {
        public:
            std::vector<std::shared_ptr<C>> GuiElements;
            GuiHandler();
            void addGuiElem(...);
            void DrawElements(sf::RenderWindow& window);
    };
}

menuhandler.cpp

#include <SFML/Graphics.hpp>
#include <vector>
#include <memory>
#include "menuhandler.hpp"

void Gui::GuiBase::SetPos(float newX, float newY)
{
    PosX = newX;
    PosY = newY;
}

void Gui::GuiBase::Move(float newX, float newY, float rate)
{

}

Gui::Button::Button(float x, float y, float width, float height, sf::String text, sf::Font& font, unsigned int textSize)
{
    PosX = x;
    PosY = y;
    Width = width;
    Height = height;
    textDisplay.setFont(font);
    textDisplay.setString(text);
    textDisplay.setCharacterSize(textSize);
    textDisplay.setPosition(x, y);
}

void Gui::Button::SetText(sf::String newText)
{
    textDisplay.setString(newText);
}

template <class C>
Gui::GuiHandler<C>::GuiHandler()
{
}

template <class C>
void Gui::GuiHandler<C>::addGuiElem(...)
{
    GuiElements.emplace_back(new C(...));
}

template <class C>
void Gui::GuiHandler<C>::DrawElements(sf::RenderWindow& window)
{
    for (auto i: GuiElements)
    {
        window.draw(i->textDisplay);
        //window.draw(i->imgDisplay);
    }
}

What am I doing wrong here? help please...

 

Share this post


Link to post
Share on other sites
Advertisement
How about making a 10-line program that shows the problem? Do I really need to install SFML to try to reproduce the problem you are having?

EDIT: Anyway, this line seems plain wrong:
    GuiElements.emplace_back(new C(...));
What do you think that is doing?

Look up varargs and see some examples of usage. Edited by Álvaro

Share this post


Link to post
Share on other sites

Note that right now C++ has two language features for variadic arguments: the old C style variadic functions and variadic template function parameters. You are using the syntax for the former. However, you can't do argument forwarding with C-style variadic functions. You'll need variadic templates for that.

Share this post


Link to post
Share on other sites

SiCrane mentioned variadic template parameters. Here's the syntax:

template<typename ...Args>
void Blah(const std::string &unrelatedA, int unrelatedB, Args&& ...args)
{
    Object object( std::forward<Args>(args)... );
}

Share this post


Link to post
Share on other sites

 

SiCrane mentioned variadic template parameters. Here's the syntax:

template<typename ...Args>
void Blah(const std::string &unrelatedA, int unrelatedB, Args&& ...args)
{
    Object object( std::forward<Args>(args)... );
}

I think I'll try and do that, tho, how would I declare that in a header file? should I simply do:

 

void Blah(const std::string &unrelatedA, int unrelatedB, Args&& ...args);

Or should I do something like:

 

 

template<typename ...Args>
void Blah(const std::string &unrelatedA, int unrelatedB, Args&& ...args);

Share this post


Link to post
Share on other sites

Ok, so I've made a test program:

test.cpp

#include <vector>
#include <memory>
#include <iostream>

class Base
{
    public:
        int MyValue;
        int getVal();
};

int Base::getVal()
{
    std::cout << "My value is: " << MyValue << std::endl;
}

class A : public Base
{
    public:
        A(int i);
};

A::A(int i)
{
    MyValue = i;
}

class handler
{
    public:
        std::vector<std::unique_ptr<Base>> objs;
        handler();
        template <class T, class... Args>
        void addObj(T, Args&&... args);
};

handler::handler() {}

template <typename T, typename... Args>
void handler::addObj(T, Args&&... args)
{
    objs.push_back(std::unique_ptr<T>(new T(args...)));
}

int main()
{
    handler handlerA;
    handlerA.addObj(A, 1);
}

I get an error tho:

 

test.cpp||In function 'int main()':|
test.cpp|48|error: expected primary-expression before ',' token|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
 

I don't know what's causing that error sad.png

Share this post


Link to post
Share on other sites
You can't pass a type as an argument. Try this instead:

#include <vector>
#include <memory>
#include <iostream>

class Base
{
    public:
        int MyValue;
        int getVal();
};

int Base::getVal()
{
    std::cout << "My value is: " << MyValue << std::endl;
}

class A : public Base
{
    public:
        A(int i);
};

A::A(int i)
{
    MyValue = i;
}

class handler
{
    public:
        std::vector<std::unique_ptr<Base>> objs;
        handler();
        template <class T, class... Args>
        void addObj(Args&&... args);
};

handler::handler() {}

template <typename T, typename... Args>
void handler::addObj(Args&&... args)
{
    objs.push_back(std::unique_ptr<T>(new T(args...)));
}

int main()
{
    handler handlerA;
    handlerA.addObj<A>(1);
}

Share this post


Link to post
Share on other sites

I think I'll try and do that, tho, how would I declare that in a header file? should I simply do:

 

Templated functions usually have to be in header files. The entire declaration (not just the definition) of the function needs to be visible to the caller of the function, so it can fill out the template to generate the code (this is an inaccurate oversimplification useful when learning templates).

Remember, templates aren't like regular functions, because the code for the function has to get generated only after you pass it parameter types. They get compiled into regular functions though.

 

MyFunc<int>() and MyFunc<float>() generate two different functions using the same function template.

Share this post


Link to post
Share on other sites

Ok, so I've spent a little time on trying to improve it but it always ends up with the error:

 

error: statement cannot resolve address of overloaded function

Where the error happens:

guiHandler.addObj<Gui::Button, 10.f, 20.f, 25.f, 25.f, "Button_1", &MainFont, 30u>;

Some code:

part of menuhandler.hpp:

class Button : public GuiBase
{
    public:
        Button(float x, float y, float width, float height, sf::String text, sf::Font& font, unsigned int textSize);
        bool isClicked();
        bool isMouseIn();
        void SetText(sf::String newText);
};

class GuiHandler
{
    public:
        std::vector<std::unique_ptr<GuiBase>> container;
        GuiHandler();
        template <class C, typename... Args>
        void addObj();
        void drawElements(sf::RenderWindow& window);
}; 

part of menuhandler.cpp:

template <class C, typename... Args>
void Gui::GuiHandler::addObj()
{
    container.push_back(std::unique_ptr<C>(new C(args...)));
}

I really have no idea on what causes that error to show up wacko.png. Help please.

Share this post


Link to post
Share on other sites
You appear to be passing everything as a template parameter now, including things that make absolutely no sense. On top of that you don't even call addObj then. I would strongly recommend to take a huge step back and forget about parameter packs for now. You seriously need a lot more practice and experience with basic C++ and basic templates.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!