How to create externally unmodifiable variable?
I'm developing simple simulation library and came across problem, where I have simulation Time
variable, which shouldn't be modifiable by API user (programmer) at any circumstances (just provide information about simulation time), but should be modifiable by simulation library, so it cannot be constant.
This is what i came up with yet but it seems a little bit tricky to me
double simTime; // Internal time, modified by library
const double& Time = simTime; // Time info provided for programmer in API
Is there any better approach for this?
c++ code-design
add a comment |
I'm developing simple simulation library and came across problem, where I have simulation Time
variable, which shouldn't be modifiable by API user (programmer) at any circumstances (just provide information about simulation time), but should be modifiable by simulation library, so it cannot be constant.
This is what i came up with yet but it seems a little bit tricky to me
double simTime; // Internal time, modified by library
const double& Time = simTime; // Time info provided for programmer in API
Is there any better approach for this?
c++ code-design
add a comment |
I'm developing simple simulation library and came across problem, where I have simulation Time
variable, which shouldn't be modifiable by API user (programmer) at any circumstances (just provide information about simulation time), but should be modifiable by simulation library, so it cannot be constant.
This is what i came up with yet but it seems a little bit tricky to me
double simTime; // Internal time, modified by library
const double& Time = simTime; // Time info provided for programmer in API
Is there any better approach for this?
c++ code-design
I'm developing simple simulation library and came across problem, where I have simulation Time
variable, which shouldn't be modifiable by API user (programmer) at any circumstances (just provide information about simulation time), but should be modifiable by simulation library, so it cannot be constant.
This is what i came up with yet but it seems a little bit tricky to me
double simTime; // Internal time, modified by library
const double& Time = simTime; // Time info provided for programmer in API
Is there any better approach for this?
c++ code-design
c++ code-design
edited Dec 31 '18 at 16:08
Filip Kočica
asked Dec 29 '18 at 19:03
Filip KočicaFilip Kočica
5,8562732
5,8562732
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
Instead of const double &
you can change your API to provide a function double getTime();
which returns the value of simTime
.
2
Agreed. Even if it means some extra time to execute the function, this is better in terms of design and separation.
– Matthieu Brucher
Dec 29 '18 at 19:10
3
Maybe. A smart enough compiler may inline or otherwise eliminate it.
– user4581301
Dec 29 '18 at 19:13
5
@FilipKočica Try benchmarking with the function and without to see if it has any negative impact before avoiding it: premature optimisation etc etc.
– hnefatl
Dec 29 '18 at 19:25
3
@Galik It cannot be inlined in the API header, because the implementation will be in the library. Otherwise, if you put the inline implementation in the header, this means you can access the variable in the header (i.e. from user code), which defeats the purpose of encapsulating it in the first place.
– Georgi Gerganov
Dec 29 '18 at 19:52
3
@Galik Linkage.
– Lightness Races in Orbit
Dec 29 '18 at 20:39
|
show 8 more comments
I find the const double&
-solution rather straight forward and elegant, and I don't see any negative side effects.
The only thing is that your library should declare simTime
either as static
or in an anonymous namespace such that it cannot be addressed from outside. Otherwise, any extern double simTime
in any other translation unit would expose simTime
.
So write...
// library.cpp:
static double simTime;
const double &simTimePublic = simTime;
// library.h:
extern const double &simTimePublic;
// userCode.cpp:
#include "library.h"
...
double simTimeCopy = simTimePublic;
// simTimePublic = 1.0; // illegal
This method has disadvantage that I wont be able to use Time, more specifically set time in other modules.
– Filip Kočica
Dec 29 '18 at 19:30
@Filip Kočica: it is actually about avoiding modicifations ofsimTime
in other modules; and there is no way in C++ of distinguishing between "own" modules and modules of other users.
– Stephan Lechner
Dec 29 '18 at 19:33
Ok, but what about operations with the variable inside the library? It will be used as global?
– Vladimir Bershov
Dec 29 '18 at 20:01
@VladimirBershov Yes, it is global variable.
– Filip Kočica
Dec 29 '18 at 21:41
1
A caveat is that the SIOF is possible with this approach. This can work so long as the reference is used only after main begins. Using it in the initialization of other static objects carries the risk of nasal demons.
– StoryTeller
Dec 29 '18 at 22:44
|
show 4 more comments
You could even (in a public header) define some inline function returning an external variable whose name is long enough to not be easily guessable, e.g.
static inline double getTime(void) {
extern double somelongname_simTime; // don't use that name directly
return somelongname_simTime;
}
indeed, the name somelongname_simTime
is public, but require malice from the user to be directly used (since it is not declared at file scope in the public header file).
(and you might even use namespace
tricks)
Notice that the compiler cannot prevent undefined behavior, such as a pointer getting accidentally the address of a static
variable.
And on Linux, you could even play some visibility tricks.
With GCC specifically you might try to have two names to the same global memory location (using assembler labels), e.g. in your public header
extern volatile const double simTime_public asm ("myrealsimTime");
and in some implementation file you'll have instead
double simTime_private asm("myrealsimTime");
Of course you are abusing the compiler and the linker when playing such tricks.
(and obviously you could mix both approaches).
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%2f53972543%2fhow-to-create-externally-unmodifiable-variable%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Instead of const double &
you can change your API to provide a function double getTime();
which returns the value of simTime
.
2
Agreed. Even if it means some extra time to execute the function, this is better in terms of design and separation.
– Matthieu Brucher
Dec 29 '18 at 19:10
3
Maybe. A smart enough compiler may inline or otherwise eliminate it.
– user4581301
Dec 29 '18 at 19:13
5
@FilipKočica Try benchmarking with the function and without to see if it has any negative impact before avoiding it: premature optimisation etc etc.
– hnefatl
Dec 29 '18 at 19:25
3
@Galik It cannot be inlined in the API header, because the implementation will be in the library. Otherwise, if you put the inline implementation in the header, this means you can access the variable in the header (i.e. from user code), which defeats the purpose of encapsulating it in the first place.
– Georgi Gerganov
Dec 29 '18 at 19:52
3
@Galik Linkage.
– Lightness Races in Orbit
Dec 29 '18 at 20:39
|
show 8 more comments
Instead of const double &
you can change your API to provide a function double getTime();
which returns the value of simTime
.
2
Agreed. Even if it means some extra time to execute the function, this is better in terms of design and separation.
– Matthieu Brucher
Dec 29 '18 at 19:10
3
Maybe. A smart enough compiler may inline or otherwise eliminate it.
– user4581301
Dec 29 '18 at 19:13
5
@FilipKočica Try benchmarking with the function and without to see if it has any negative impact before avoiding it: premature optimisation etc etc.
– hnefatl
Dec 29 '18 at 19:25
3
@Galik It cannot be inlined in the API header, because the implementation will be in the library. Otherwise, if you put the inline implementation in the header, this means you can access the variable in the header (i.e. from user code), which defeats the purpose of encapsulating it in the first place.
– Georgi Gerganov
Dec 29 '18 at 19:52
3
@Galik Linkage.
– Lightness Races in Orbit
Dec 29 '18 at 20:39
|
show 8 more comments
Instead of const double &
you can change your API to provide a function double getTime();
which returns the value of simTime
.
Instead of const double &
you can change your API to provide a function double getTime();
which returns the value of simTime
.
answered Dec 29 '18 at 19:07
Georgi GerganovGeorgi Gerganov
761611
761611
2
Agreed. Even if it means some extra time to execute the function, this is better in terms of design and separation.
– Matthieu Brucher
Dec 29 '18 at 19:10
3
Maybe. A smart enough compiler may inline or otherwise eliminate it.
– user4581301
Dec 29 '18 at 19:13
5
@FilipKočica Try benchmarking with the function and without to see if it has any negative impact before avoiding it: premature optimisation etc etc.
– hnefatl
Dec 29 '18 at 19:25
3
@Galik It cannot be inlined in the API header, because the implementation will be in the library. Otherwise, if you put the inline implementation in the header, this means you can access the variable in the header (i.e. from user code), which defeats the purpose of encapsulating it in the first place.
– Georgi Gerganov
Dec 29 '18 at 19:52
3
@Galik Linkage.
– Lightness Races in Orbit
Dec 29 '18 at 20:39
|
show 8 more comments
2
Agreed. Even if it means some extra time to execute the function, this is better in terms of design and separation.
– Matthieu Brucher
Dec 29 '18 at 19:10
3
Maybe. A smart enough compiler may inline or otherwise eliminate it.
– user4581301
Dec 29 '18 at 19:13
5
@FilipKočica Try benchmarking with the function and without to see if it has any negative impact before avoiding it: premature optimisation etc etc.
– hnefatl
Dec 29 '18 at 19:25
3
@Galik It cannot be inlined in the API header, because the implementation will be in the library. Otherwise, if you put the inline implementation in the header, this means you can access the variable in the header (i.e. from user code), which defeats the purpose of encapsulating it in the first place.
– Georgi Gerganov
Dec 29 '18 at 19:52
3
@Galik Linkage.
– Lightness Races in Orbit
Dec 29 '18 at 20:39
2
2
Agreed. Even if it means some extra time to execute the function, this is better in terms of design and separation.
– Matthieu Brucher
Dec 29 '18 at 19:10
Agreed. Even if it means some extra time to execute the function, this is better in terms of design and separation.
– Matthieu Brucher
Dec 29 '18 at 19:10
3
3
Maybe. A smart enough compiler may inline or otherwise eliminate it.
– user4581301
Dec 29 '18 at 19:13
Maybe. A smart enough compiler may inline or otherwise eliminate it.
– user4581301
Dec 29 '18 at 19:13
5
5
@FilipKočica Try benchmarking with the function and without to see if it has any negative impact before avoiding it: premature optimisation etc etc.
– hnefatl
Dec 29 '18 at 19:25
@FilipKočica Try benchmarking with the function and without to see if it has any negative impact before avoiding it: premature optimisation etc etc.
– hnefatl
Dec 29 '18 at 19:25
3
3
@Galik It cannot be inlined in the API header, because the implementation will be in the library. Otherwise, if you put the inline implementation in the header, this means you can access the variable in the header (i.e. from user code), which defeats the purpose of encapsulating it in the first place.
– Georgi Gerganov
Dec 29 '18 at 19:52
@Galik It cannot be inlined in the API header, because the implementation will be in the library. Otherwise, if you put the inline implementation in the header, this means you can access the variable in the header (i.e. from user code), which defeats the purpose of encapsulating it in the first place.
– Georgi Gerganov
Dec 29 '18 at 19:52
3
3
@Galik Linkage.
– Lightness Races in Orbit
Dec 29 '18 at 20:39
@Galik Linkage.
– Lightness Races in Orbit
Dec 29 '18 at 20:39
|
show 8 more comments
I find the const double&
-solution rather straight forward and elegant, and I don't see any negative side effects.
The only thing is that your library should declare simTime
either as static
or in an anonymous namespace such that it cannot be addressed from outside. Otherwise, any extern double simTime
in any other translation unit would expose simTime
.
So write...
// library.cpp:
static double simTime;
const double &simTimePublic = simTime;
// library.h:
extern const double &simTimePublic;
// userCode.cpp:
#include "library.h"
...
double simTimeCopy = simTimePublic;
// simTimePublic = 1.0; // illegal
This method has disadvantage that I wont be able to use Time, more specifically set time in other modules.
– Filip Kočica
Dec 29 '18 at 19:30
@Filip Kočica: it is actually about avoiding modicifations ofsimTime
in other modules; and there is no way in C++ of distinguishing between "own" modules and modules of other users.
– Stephan Lechner
Dec 29 '18 at 19:33
Ok, but what about operations with the variable inside the library? It will be used as global?
– Vladimir Bershov
Dec 29 '18 at 20:01
@VladimirBershov Yes, it is global variable.
– Filip Kočica
Dec 29 '18 at 21:41
1
A caveat is that the SIOF is possible with this approach. This can work so long as the reference is used only after main begins. Using it in the initialization of other static objects carries the risk of nasal demons.
– StoryTeller
Dec 29 '18 at 22:44
|
show 4 more comments
I find the const double&
-solution rather straight forward and elegant, and I don't see any negative side effects.
The only thing is that your library should declare simTime
either as static
or in an anonymous namespace such that it cannot be addressed from outside. Otherwise, any extern double simTime
in any other translation unit would expose simTime
.
So write...
// library.cpp:
static double simTime;
const double &simTimePublic = simTime;
// library.h:
extern const double &simTimePublic;
// userCode.cpp:
#include "library.h"
...
double simTimeCopy = simTimePublic;
// simTimePublic = 1.0; // illegal
This method has disadvantage that I wont be able to use Time, more specifically set time in other modules.
– Filip Kočica
Dec 29 '18 at 19:30
@Filip Kočica: it is actually about avoiding modicifations ofsimTime
in other modules; and there is no way in C++ of distinguishing between "own" modules and modules of other users.
– Stephan Lechner
Dec 29 '18 at 19:33
Ok, but what about operations with the variable inside the library? It will be used as global?
– Vladimir Bershov
Dec 29 '18 at 20:01
@VladimirBershov Yes, it is global variable.
– Filip Kočica
Dec 29 '18 at 21:41
1
A caveat is that the SIOF is possible with this approach. This can work so long as the reference is used only after main begins. Using it in the initialization of other static objects carries the risk of nasal demons.
– StoryTeller
Dec 29 '18 at 22:44
|
show 4 more comments
I find the const double&
-solution rather straight forward and elegant, and I don't see any negative side effects.
The only thing is that your library should declare simTime
either as static
or in an anonymous namespace such that it cannot be addressed from outside. Otherwise, any extern double simTime
in any other translation unit would expose simTime
.
So write...
// library.cpp:
static double simTime;
const double &simTimePublic = simTime;
// library.h:
extern const double &simTimePublic;
// userCode.cpp:
#include "library.h"
...
double simTimeCopy = simTimePublic;
// simTimePublic = 1.0; // illegal
I find the const double&
-solution rather straight forward and elegant, and I don't see any negative side effects.
The only thing is that your library should declare simTime
either as static
or in an anonymous namespace such that it cannot be addressed from outside. Otherwise, any extern double simTime
in any other translation unit would expose simTime
.
So write...
// library.cpp:
static double simTime;
const double &simTimePublic = simTime;
// library.h:
extern const double &simTimePublic;
// userCode.cpp:
#include "library.h"
...
double simTimeCopy = simTimePublic;
// simTimePublic = 1.0; // illegal
answered Dec 29 '18 at 19:22
Stephan LechnerStephan Lechner
27.8k32142
27.8k32142
This method has disadvantage that I wont be able to use Time, more specifically set time in other modules.
– Filip Kočica
Dec 29 '18 at 19:30
@Filip Kočica: it is actually about avoiding modicifations ofsimTime
in other modules; and there is no way in C++ of distinguishing between "own" modules and modules of other users.
– Stephan Lechner
Dec 29 '18 at 19:33
Ok, but what about operations with the variable inside the library? It will be used as global?
– Vladimir Bershov
Dec 29 '18 at 20:01
@VladimirBershov Yes, it is global variable.
– Filip Kočica
Dec 29 '18 at 21:41
1
A caveat is that the SIOF is possible with this approach. This can work so long as the reference is used only after main begins. Using it in the initialization of other static objects carries the risk of nasal demons.
– StoryTeller
Dec 29 '18 at 22:44
|
show 4 more comments
This method has disadvantage that I wont be able to use Time, more specifically set time in other modules.
– Filip Kočica
Dec 29 '18 at 19:30
@Filip Kočica: it is actually about avoiding modicifations ofsimTime
in other modules; and there is no way in C++ of distinguishing between "own" modules and modules of other users.
– Stephan Lechner
Dec 29 '18 at 19:33
Ok, but what about operations with the variable inside the library? It will be used as global?
– Vladimir Bershov
Dec 29 '18 at 20:01
@VladimirBershov Yes, it is global variable.
– Filip Kočica
Dec 29 '18 at 21:41
1
A caveat is that the SIOF is possible with this approach. This can work so long as the reference is used only after main begins. Using it in the initialization of other static objects carries the risk of nasal demons.
– StoryTeller
Dec 29 '18 at 22:44
This method has disadvantage that I wont be able to use Time, more specifically set time in other modules.
– Filip Kočica
Dec 29 '18 at 19:30
This method has disadvantage that I wont be able to use Time, more specifically set time in other modules.
– Filip Kočica
Dec 29 '18 at 19:30
@Filip Kočica: it is actually about avoiding modicifations of
simTime
in other modules; and there is no way in C++ of distinguishing between "own" modules and modules of other users.– Stephan Lechner
Dec 29 '18 at 19:33
@Filip Kočica: it is actually about avoiding modicifations of
simTime
in other modules; and there is no way in C++ of distinguishing between "own" modules and modules of other users.– Stephan Lechner
Dec 29 '18 at 19:33
Ok, but what about operations with the variable inside the library? It will be used as global?
– Vladimir Bershov
Dec 29 '18 at 20:01
Ok, but what about operations with the variable inside the library? It will be used as global?
– Vladimir Bershov
Dec 29 '18 at 20:01
@VladimirBershov Yes, it is global variable.
– Filip Kočica
Dec 29 '18 at 21:41
@VladimirBershov Yes, it is global variable.
– Filip Kočica
Dec 29 '18 at 21:41
1
1
A caveat is that the SIOF is possible with this approach. This can work so long as the reference is used only after main begins. Using it in the initialization of other static objects carries the risk of nasal demons.
– StoryTeller
Dec 29 '18 at 22:44
A caveat is that the SIOF is possible with this approach. This can work so long as the reference is used only after main begins. Using it in the initialization of other static objects carries the risk of nasal demons.
– StoryTeller
Dec 29 '18 at 22:44
|
show 4 more comments
You could even (in a public header) define some inline function returning an external variable whose name is long enough to not be easily guessable, e.g.
static inline double getTime(void) {
extern double somelongname_simTime; // don't use that name directly
return somelongname_simTime;
}
indeed, the name somelongname_simTime
is public, but require malice from the user to be directly used (since it is not declared at file scope in the public header file).
(and you might even use namespace
tricks)
Notice that the compiler cannot prevent undefined behavior, such as a pointer getting accidentally the address of a static
variable.
And on Linux, you could even play some visibility tricks.
With GCC specifically you might try to have two names to the same global memory location (using assembler labels), e.g. in your public header
extern volatile const double simTime_public asm ("myrealsimTime");
and in some implementation file you'll have instead
double simTime_private asm("myrealsimTime");
Of course you are abusing the compiler and the linker when playing such tricks.
(and obviously you could mix both approaches).
add a comment |
You could even (in a public header) define some inline function returning an external variable whose name is long enough to not be easily guessable, e.g.
static inline double getTime(void) {
extern double somelongname_simTime; // don't use that name directly
return somelongname_simTime;
}
indeed, the name somelongname_simTime
is public, but require malice from the user to be directly used (since it is not declared at file scope in the public header file).
(and you might even use namespace
tricks)
Notice that the compiler cannot prevent undefined behavior, such as a pointer getting accidentally the address of a static
variable.
And on Linux, you could even play some visibility tricks.
With GCC specifically you might try to have two names to the same global memory location (using assembler labels), e.g. in your public header
extern volatile const double simTime_public asm ("myrealsimTime");
and in some implementation file you'll have instead
double simTime_private asm("myrealsimTime");
Of course you are abusing the compiler and the linker when playing such tricks.
(and obviously you could mix both approaches).
add a comment |
You could even (in a public header) define some inline function returning an external variable whose name is long enough to not be easily guessable, e.g.
static inline double getTime(void) {
extern double somelongname_simTime; // don't use that name directly
return somelongname_simTime;
}
indeed, the name somelongname_simTime
is public, but require malice from the user to be directly used (since it is not declared at file scope in the public header file).
(and you might even use namespace
tricks)
Notice that the compiler cannot prevent undefined behavior, such as a pointer getting accidentally the address of a static
variable.
And on Linux, you could even play some visibility tricks.
With GCC specifically you might try to have two names to the same global memory location (using assembler labels), e.g. in your public header
extern volatile const double simTime_public asm ("myrealsimTime");
and in some implementation file you'll have instead
double simTime_private asm("myrealsimTime");
Of course you are abusing the compiler and the linker when playing such tricks.
(and obviously you could mix both approaches).
You could even (in a public header) define some inline function returning an external variable whose name is long enough to not be easily guessable, e.g.
static inline double getTime(void) {
extern double somelongname_simTime; // don't use that name directly
return somelongname_simTime;
}
indeed, the name somelongname_simTime
is public, but require malice from the user to be directly used (since it is not declared at file scope in the public header file).
(and you might even use namespace
tricks)
Notice that the compiler cannot prevent undefined behavior, such as a pointer getting accidentally the address of a static
variable.
And on Linux, you could even play some visibility tricks.
With GCC specifically you might try to have two names to the same global memory location (using assembler labels), e.g. in your public header
extern volatile const double simTime_public asm ("myrealsimTime");
and in some implementation file you'll have instead
double simTime_private asm("myrealsimTime");
Of course you are abusing the compiler and the linker when playing such tricks.
(and obviously you could mix both approaches).
edited Dec 31 '18 at 16:36
answered Dec 31 '18 at 16:21
Basile StarynkevitchBasile Starynkevitch
177k13166364
177k13166364
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%2f53972543%2fhow-to-create-externally-unmodifiable-variable%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