Singleton : avoid GetIntance()
Everyone knows the singleton pattern (very simple exemple) :
class Singleton
private:
static Singleton* instance;
public:
static Singleton* GetInstance() return instance;
void Foo()
;
And the use :
Singleton::GetInstance()->Foo();
I wonder, why this GetInstance()
is mandatory. I've tried to find a way to eliminate the call to this function, to be able to write for exemple... :
Singleton->Foo();
... using the class name the same way I use a variable, because of the singleton pattern, and others security like deleting the public constructor for exemple, we are sure that we only have a single instance, so why not "using the class as a variable" (quote, unquote, only syntaxic speaking of course !).
Each time, a C++ rule prohibit following exemples :
Singleton->Foo(); // (1)
Singleton()->Foo(); // (2)
Singleton.Foo(); // (3)
Singleton::Foo(); // (4)
Because :
- (1)
static Singleton* operator->() return instance;
is impossible, Class Member Access Operator (->) overload can't be static (see C2801), same for (2) with operator () - (3) and (4) operators . and :: can't be overloaded
Only solution here : Macros, but I'm actually using macros, and I want to find an other way and avoiding macros for this...
It's only a syntaxic interrogation, I'm not here to debate about pros and cons of singletons, but I wonder why C++ permit so many things for simplify the use syntax of users classes with overloads, user literals, and we can't eliminate this little function from the pattern.
I don't expect a solution (but if there is one, it would be great), it's just to understand why, to know if there is a explanation, a design reason, a security reason or anything else !
Thanks in advance !
c++ singleton
add a comment |
Everyone knows the singleton pattern (very simple exemple) :
class Singleton
private:
static Singleton* instance;
public:
static Singleton* GetInstance() return instance;
void Foo()
;
And the use :
Singleton::GetInstance()->Foo();
I wonder, why this GetInstance()
is mandatory. I've tried to find a way to eliminate the call to this function, to be able to write for exemple... :
Singleton->Foo();
... using the class name the same way I use a variable, because of the singleton pattern, and others security like deleting the public constructor for exemple, we are sure that we only have a single instance, so why not "using the class as a variable" (quote, unquote, only syntaxic speaking of course !).
Each time, a C++ rule prohibit following exemples :
Singleton->Foo(); // (1)
Singleton()->Foo(); // (2)
Singleton.Foo(); // (3)
Singleton::Foo(); // (4)
Because :
- (1)
static Singleton* operator->() return instance;
is impossible, Class Member Access Operator (->) overload can't be static (see C2801), same for (2) with operator () - (3) and (4) operators . and :: can't be overloaded
Only solution here : Macros, but I'm actually using macros, and I want to find an other way and avoiding macros for this...
It's only a syntaxic interrogation, I'm not here to debate about pros and cons of singletons, but I wonder why C++ permit so many things for simplify the use syntax of users classes with overloads, user literals, and we can't eliminate this little function from the pattern.
I don't expect a solution (but if there is one, it would be great), it's just to understand why, to know if there is a explanation, a design reason, a security reason or anything else !
Thanks in advance !
c++ singleton
1
BTW, This method comes strongly recommended: stackoverflow.com/a/1008289/3807729
– Galik
Nov 11 '18 at 0:54
You can hide a singleton with a façade of static class functions, e.g.,static void Foo() GetInstance()->Foo();
, then the callsite would only have to doSingleton::Foo();
which is pretty close to (4).
– Eljay
Nov 11 '18 at 0:59
@Galik, interesting link, thanks. But i will go a little it further : I understand that this method can be important for destruction explained in your link, and in fact, I do not want to remove it from the class, only from the user code. Admit that operator -> can be static I could write :static Singleton* operator->() return GetInstance();
, and useSingleton->Foo();
, the problem is not the existence of the method, but the call to this method in user code !
– Monk
Nov 11 '18 at 1:03
@Eljay It's what I've thinking, but it mean that we always have to change all methods of all singletons class to statics methods or duplicate all publics methods to get a static version calling a non static version of the method... It's why I just speak of syntax, I don't want to change meaning of the existing code !
– Monk
Nov 11 '18 at 1:06
There is a different pattern called the Monostate pattern. Very similar to a Singleton. All the functions are static functions ("class functions"), and all the data is in static variables ("class variables"). Any instances are empty, so usage just acts as a proxy for the class functions and class variables.
– Eljay
Nov 11 '18 at 13:32
add a comment |
Everyone knows the singleton pattern (very simple exemple) :
class Singleton
private:
static Singleton* instance;
public:
static Singleton* GetInstance() return instance;
void Foo()
;
And the use :
Singleton::GetInstance()->Foo();
I wonder, why this GetInstance()
is mandatory. I've tried to find a way to eliminate the call to this function, to be able to write for exemple... :
Singleton->Foo();
... using the class name the same way I use a variable, because of the singleton pattern, and others security like deleting the public constructor for exemple, we are sure that we only have a single instance, so why not "using the class as a variable" (quote, unquote, only syntaxic speaking of course !).
Each time, a C++ rule prohibit following exemples :
Singleton->Foo(); // (1)
Singleton()->Foo(); // (2)
Singleton.Foo(); // (3)
Singleton::Foo(); // (4)
Because :
- (1)
static Singleton* operator->() return instance;
is impossible, Class Member Access Operator (->) overload can't be static (see C2801), same for (2) with operator () - (3) and (4) operators . and :: can't be overloaded
Only solution here : Macros, but I'm actually using macros, and I want to find an other way and avoiding macros for this...
It's only a syntaxic interrogation, I'm not here to debate about pros and cons of singletons, but I wonder why C++ permit so many things for simplify the use syntax of users classes with overloads, user literals, and we can't eliminate this little function from the pattern.
I don't expect a solution (but if there is one, it would be great), it's just to understand why, to know if there is a explanation, a design reason, a security reason or anything else !
Thanks in advance !
c++ singleton
Everyone knows the singleton pattern (very simple exemple) :
class Singleton
private:
static Singleton* instance;
public:
static Singleton* GetInstance() return instance;
void Foo()
;
And the use :
Singleton::GetInstance()->Foo();
I wonder, why this GetInstance()
is mandatory. I've tried to find a way to eliminate the call to this function, to be able to write for exemple... :
Singleton->Foo();
... using the class name the same way I use a variable, because of the singleton pattern, and others security like deleting the public constructor for exemple, we are sure that we only have a single instance, so why not "using the class as a variable" (quote, unquote, only syntaxic speaking of course !).
Each time, a C++ rule prohibit following exemples :
Singleton->Foo(); // (1)
Singleton()->Foo(); // (2)
Singleton.Foo(); // (3)
Singleton::Foo(); // (4)
Because :
- (1)
static Singleton* operator->() return instance;
is impossible, Class Member Access Operator (->) overload can't be static (see C2801), same for (2) with operator () - (3) and (4) operators . and :: can't be overloaded
Only solution here : Macros, but I'm actually using macros, and I want to find an other way and avoiding macros for this...
It's only a syntaxic interrogation, I'm not here to debate about pros and cons of singletons, but I wonder why C++ permit so many things for simplify the use syntax of users classes with overloads, user literals, and we can't eliminate this little function from the pattern.
I don't expect a solution (but if there is one, it would be great), it's just to understand why, to know if there is a explanation, a design reason, a security reason or anything else !
Thanks in advance !
c++ singleton
c++ singleton
asked Nov 11 '18 at 0:48
MonkMonk
143
143
1
BTW, This method comes strongly recommended: stackoverflow.com/a/1008289/3807729
– Galik
Nov 11 '18 at 0:54
You can hide a singleton with a façade of static class functions, e.g.,static void Foo() GetInstance()->Foo();
, then the callsite would only have to doSingleton::Foo();
which is pretty close to (4).
– Eljay
Nov 11 '18 at 0:59
@Galik, interesting link, thanks. But i will go a little it further : I understand that this method can be important for destruction explained in your link, and in fact, I do not want to remove it from the class, only from the user code. Admit that operator -> can be static I could write :static Singleton* operator->() return GetInstance();
, and useSingleton->Foo();
, the problem is not the existence of the method, but the call to this method in user code !
– Monk
Nov 11 '18 at 1:03
@Eljay It's what I've thinking, but it mean that we always have to change all methods of all singletons class to statics methods or duplicate all publics methods to get a static version calling a non static version of the method... It's why I just speak of syntax, I don't want to change meaning of the existing code !
– Monk
Nov 11 '18 at 1:06
There is a different pattern called the Monostate pattern. Very similar to a Singleton. All the functions are static functions ("class functions"), and all the data is in static variables ("class variables"). Any instances are empty, so usage just acts as a proxy for the class functions and class variables.
– Eljay
Nov 11 '18 at 13:32
add a comment |
1
BTW, This method comes strongly recommended: stackoverflow.com/a/1008289/3807729
– Galik
Nov 11 '18 at 0:54
You can hide a singleton with a façade of static class functions, e.g.,static void Foo() GetInstance()->Foo();
, then the callsite would only have to doSingleton::Foo();
which is pretty close to (4).
– Eljay
Nov 11 '18 at 0:59
@Galik, interesting link, thanks. But i will go a little it further : I understand that this method can be important for destruction explained in your link, and in fact, I do not want to remove it from the class, only from the user code. Admit that operator -> can be static I could write :static Singleton* operator->() return GetInstance();
, and useSingleton->Foo();
, the problem is not the existence of the method, but the call to this method in user code !
– Monk
Nov 11 '18 at 1:03
@Eljay It's what I've thinking, but it mean that we always have to change all methods of all singletons class to statics methods or duplicate all publics methods to get a static version calling a non static version of the method... It's why I just speak of syntax, I don't want to change meaning of the existing code !
– Monk
Nov 11 '18 at 1:06
There is a different pattern called the Monostate pattern. Very similar to a Singleton. All the functions are static functions ("class functions"), and all the data is in static variables ("class variables"). Any instances are empty, so usage just acts as a proxy for the class functions and class variables.
– Eljay
Nov 11 '18 at 13:32
1
1
BTW, This method comes strongly recommended: stackoverflow.com/a/1008289/3807729
– Galik
Nov 11 '18 at 0:54
BTW, This method comes strongly recommended: stackoverflow.com/a/1008289/3807729
– Galik
Nov 11 '18 at 0:54
You can hide a singleton with a façade of static class functions, e.g.,
static void Foo() GetInstance()->Foo();
, then the callsite would only have to do Singleton::Foo();
which is pretty close to (4).– Eljay
Nov 11 '18 at 0:59
You can hide a singleton with a façade of static class functions, e.g.,
static void Foo() GetInstance()->Foo();
, then the callsite would only have to do Singleton::Foo();
which is pretty close to (4).– Eljay
Nov 11 '18 at 0:59
@Galik, interesting link, thanks. But i will go a little it further : I understand that this method can be important for destruction explained in your link, and in fact, I do not want to remove it from the class, only from the user code. Admit that operator -> can be static I could write :
static Singleton* operator->() return GetInstance();
, and use Singleton->Foo();
, the problem is not the existence of the method, but the call to this method in user code !– Monk
Nov 11 '18 at 1:03
@Galik, interesting link, thanks. But i will go a little it further : I understand that this method can be important for destruction explained in your link, and in fact, I do not want to remove it from the class, only from the user code. Admit that operator -> can be static I could write :
static Singleton* operator->() return GetInstance();
, and use Singleton->Foo();
, the problem is not the existence of the method, but the call to this method in user code !– Monk
Nov 11 '18 at 1:03
@Eljay It's what I've thinking, but it mean that we always have to change all methods of all singletons class to statics methods or duplicate all publics methods to get a static version calling a non static version of the method... It's why I just speak of syntax, I don't want to change meaning of the existing code !
– Monk
Nov 11 '18 at 1:06
@Eljay It's what I've thinking, but it mean that we always have to change all methods of all singletons class to statics methods or duplicate all publics methods to get a static version calling a non static version of the method... It's why I just speak of syntax, I don't want to change meaning of the existing code !
– Monk
Nov 11 '18 at 1:06
There is a different pattern called the Monostate pattern. Very similar to a Singleton. All the functions are static functions ("class functions"), and all the data is in static variables ("class variables"). Any instances are empty, so usage just acts as a proxy for the class functions and class variables.
– Eljay
Nov 11 '18 at 13:32
There is a different pattern called the Monostate pattern. Very similar to a Singleton. All the functions are static functions ("class functions"), and all the data is in static variables ("class variables"). Any instances are empty, so usage just acts as a proxy for the class functions and class variables.
– Eljay
Nov 11 '18 at 13:32
add a comment |
2 Answers
2
active
oldest
votes
Well one way to do this is to reduce the singleton part of the problem to just the data and create static functions that access that data through the "instance" function (called self()
in this example):
class Singletonish
private:
// single (inaccessible) instance of the data
static auto& self()
static struct
std::string s = "unset";
int i = 0;
data;
return data;
public:
static void foo()
// foo code here
self().s = "hello";
self().i = 9;
static void woo()
// woo code here
std::cout << self().s << 'n';
std::cout << self().i << 'n';
;
int main()
Singletonish::woo();
Singletonish::foo();
Singletonish::woo();
Output:
unset
0
hello
9
Personally I recommend just doing it the normal way: https://stackoverflow.com/a/1008289/3807729
For the sake of ensuring readability, maintainability, and frankly, sanity, I second your closing personal stance.
– WhozCraig
Nov 11 '18 at 1:19
add a comment |
I can think of the following way in C++11
:
#include <memory>
struct singleton
int i;
;
template <class Singleton_t>
struct singleton_holder
auto* operator -> () const noexcept
static Singleton_t s;
return std::addressof(s);
;
// optional C++14 feature, can be commented if wanted
template <class Singleton_t>
constexpr const static /* inline */ singleton_holder<Singleton_t> singleton_v;
Now, with this code, you can just create singleton_holder<singleton> s
and use s->i
to access the member of the singleton
directly.
Or you can use C++14
way: singleton_v<singleton>->i
to access member of the singleton
directly.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244857%2fsingleton-avoid-getintance%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Well one way to do this is to reduce the singleton part of the problem to just the data and create static functions that access that data through the "instance" function (called self()
in this example):
class Singletonish
private:
// single (inaccessible) instance of the data
static auto& self()
static struct
std::string s = "unset";
int i = 0;
data;
return data;
public:
static void foo()
// foo code here
self().s = "hello";
self().i = 9;
static void woo()
// woo code here
std::cout << self().s << 'n';
std::cout << self().i << 'n';
;
int main()
Singletonish::woo();
Singletonish::foo();
Singletonish::woo();
Output:
unset
0
hello
9
Personally I recommend just doing it the normal way: https://stackoverflow.com/a/1008289/3807729
For the sake of ensuring readability, maintainability, and frankly, sanity, I second your closing personal stance.
– WhozCraig
Nov 11 '18 at 1:19
add a comment |
Well one way to do this is to reduce the singleton part of the problem to just the data and create static functions that access that data through the "instance" function (called self()
in this example):
class Singletonish
private:
// single (inaccessible) instance of the data
static auto& self()
static struct
std::string s = "unset";
int i = 0;
data;
return data;
public:
static void foo()
// foo code here
self().s = "hello";
self().i = 9;
static void woo()
// woo code here
std::cout << self().s << 'n';
std::cout << self().i << 'n';
;
int main()
Singletonish::woo();
Singletonish::foo();
Singletonish::woo();
Output:
unset
0
hello
9
Personally I recommend just doing it the normal way: https://stackoverflow.com/a/1008289/3807729
For the sake of ensuring readability, maintainability, and frankly, sanity, I second your closing personal stance.
– WhozCraig
Nov 11 '18 at 1:19
add a comment |
Well one way to do this is to reduce the singleton part of the problem to just the data and create static functions that access that data through the "instance" function (called self()
in this example):
class Singletonish
private:
// single (inaccessible) instance of the data
static auto& self()
static struct
std::string s = "unset";
int i = 0;
data;
return data;
public:
static void foo()
// foo code here
self().s = "hello";
self().i = 9;
static void woo()
// woo code here
std::cout << self().s << 'n';
std::cout << self().i << 'n';
;
int main()
Singletonish::woo();
Singletonish::foo();
Singletonish::woo();
Output:
unset
0
hello
9
Personally I recommend just doing it the normal way: https://stackoverflow.com/a/1008289/3807729
Well one way to do this is to reduce the singleton part of the problem to just the data and create static functions that access that data through the "instance" function (called self()
in this example):
class Singletonish
private:
// single (inaccessible) instance of the data
static auto& self()
static struct
std::string s = "unset";
int i = 0;
data;
return data;
public:
static void foo()
// foo code here
self().s = "hello";
self().i = 9;
static void woo()
// woo code here
std::cout << self().s << 'n';
std::cout << self().i << 'n';
;
int main()
Singletonish::woo();
Singletonish::foo();
Singletonish::woo();
Output:
unset
0
hello
9
Personally I recommend just doing it the normal way: https://stackoverflow.com/a/1008289/3807729
answered Nov 11 '18 at 1:16
GalikGalik
33.6k34876
33.6k34876
For the sake of ensuring readability, maintainability, and frankly, sanity, I second your closing personal stance.
– WhozCraig
Nov 11 '18 at 1:19
add a comment |
For the sake of ensuring readability, maintainability, and frankly, sanity, I second your closing personal stance.
– WhozCraig
Nov 11 '18 at 1:19
For the sake of ensuring readability, maintainability, and frankly, sanity, I second your closing personal stance.
– WhozCraig
Nov 11 '18 at 1:19
For the sake of ensuring readability, maintainability, and frankly, sanity, I second your closing personal stance.
– WhozCraig
Nov 11 '18 at 1:19
add a comment |
I can think of the following way in C++11
:
#include <memory>
struct singleton
int i;
;
template <class Singleton_t>
struct singleton_holder
auto* operator -> () const noexcept
static Singleton_t s;
return std::addressof(s);
;
// optional C++14 feature, can be commented if wanted
template <class Singleton_t>
constexpr const static /* inline */ singleton_holder<Singleton_t> singleton_v;
Now, with this code, you can just create singleton_holder<singleton> s
and use s->i
to access the member of the singleton
directly.
Or you can use C++14
way: singleton_v<singleton>->i
to access member of the singleton
directly.
add a comment |
I can think of the following way in C++11
:
#include <memory>
struct singleton
int i;
;
template <class Singleton_t>
struct singleton_holder
auto* operator -> () const noexcept
static Singleton_t s;
return std::addressof(s);
;
// optional C++14 feature, can be commented if wanted
template <class Singleton_t>
constexpr const static /* inline */ singleton_holder<Singleton_t> singleton_v;
Now, with this code, you can just create singleton_holder<singleton> s
and use s->i
to access the member of the singleton
directly.
Or you can use C++14
way: singleton_v<singleton>->i
to access member of the singleton
directly.
add a comment |
I can think of the following way in C++11
:
#include <memory>
struct singleton
int i;
;
template <class Singleton_t>
struct singleton_holder
auto* operator -> () const noexcept
static Singleton_t s;
return std::addressof(s);
;
// optional C++14 feature, can be commented if wanted
template <class Singleton_t>
constexpr const static /* inline */ singleton_holder<Singleton_t> singleton_v;
Now, with this code, you can just create singleton_holder<singleton> s
and use s->i
to access the member of the singleton
directly.
Or you can use C++14
way: singleton_v<singleton>->i
to access member of the singleton
directly.
I can think of the following way in C++11
:
#include <memory>
struct singleton
int i;
;
template <class Singleton_t>
struct singleton_holder
auto* operator -> () const noexcept
static Singleton_t s;
return std::addressof(s);
;
// optional C++14 feature, can be commented if wanted
template <class Singleton_t>
constexpr const static /* inline */ singleton_holder<Singleton_t> singleton_v;
Now, with this code, you can just create singleton_holder<singleton> s
and use s->i
to access the member of the singleton
directly.
Or you can use C++14
way: singleton_v<singleton>->i
to access member of the singleton
directly.
answered Nov 11 '18 at 1:46
JiaHao XuJiaHao Xu
639315
639315
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53244857%2fsingleton-avoid-getintance%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
BTW, This method comes strongly recommended: stackoverflow.com/a/1008289/3807729
– Galik
Nov 11 '18 at 0:54
You can hide a singleton with a façade of static class functions, e.g.,
static void Foo() GetInstance()->Foo();
, then the callsite would only have to doSingleton::Foo();
which is pretty close to (4).– Eljay
Nov 11 '18 at 0:59
@Galik, interesting link, thanks. But i will go a little it further : I understand that this method can be important for destruction explained in your link, and in fact, I do not want to remove it from the class, only from the user code. Admit that operator -> can be static I could write :
static Singleton* operator->() return GetInstance();
, and useSingleton->Foo();
, the problem is not the existence of the method, but the call to this method in user code !– Monk
Nov 11 '18 at 1:03
@Eljay It's what I've thinking, but it mean that we always have to change all methods of all singletons class to statics methods or duplicate all publics methods to get a static version calling a non static version of the method... It's why I just speak of syntax, I don't want to change meaning of the existing code !
– Monk
Nov 11 '18 at 1:06
There is a different pattern called the Monostate pattern. Very similar to a Singleton. All the functions are static functions ("class functions"), and all the data is in static variables ("class variables"). Any instances are empty, so usage just acts as a proxy for the class functions and class variables.
– Eljay
Nov 11 '18 at 13:32