Is it possible to make an enum public, in a module where the default is private?
module mod
private
enum, (public,) bind(c) !Doesn't work
enumerator(, public) :: ENUM1, ENUM2,... !Doesn't work
end enum
end module
I want to keep the module data private by default but want the enums to be public without having to list them individually like this:
public :: ENUM1, ENUM2,... !Works
I understand that enums are just integer parameters so I'm curious if it's possible to do it for all of them at once.
What you are trying to do does not conform the syntax rules from Fortran 2008 4.6.1., therefore, it is not possible to insert the public attributes in the enumeration definition.
There is also no way to put the enumerators in the public statement as a group, you must list each of them.
The enumerations were added to Fortran more or less only for C interoperability (note the obligatory bind(c)) and do not fit the rest of the language that well.
Related
MODULE MyTypeMod
TYPE MyType
PRIVATE
INTEGER, ALLOCATABLE :: Num
CONTAINS
PROCEDURE, PUBLIC :: IsNum!To check Allocation of Num
...
END TYPE MyType
CONTAINS
...
END MODULE MyTypeMod
PROGRAM testMyType
USE MyTypeMod, ONLY : MyType
...
END PROGRAM testMyType
Here In this Module and Program, Can we modify accessibility status "IsNum" type-bound procedure? Can we make the "IsNum" procedure PRIVATE in just the testMyTypeMod PROGRAM?
According to paragraph 9 of section 7.5.5 of the Fortran 2018 draft standard
A public type-bound procedure is accessible via any accessible object of the type. A private type-bound procedure is accessible only within the module containing the type definition, and within its descendants.
And so changing the accessibility of a type-bound procedure is not possible.
There is currently a proposal to update a future Fortran standard that suggests making a subset of what you want to do possible.
You may want to make a new proposal to update the standard. This is also likely the best way to find out why what you want to do is not currently possible.
Assume I first defined a type A in which a public procedure f is defined, and may also be bonded to A. In another module I have this type extended into B. However, when I use type B, I do not want f to be exposed.
By the way, I don't want to use the submod technique.
complement:
Assume type(A) is already defined:
module mA
type::A
...
contains
procedure::f
endtype
endmodule
In another module B, we extend A as:
module mB
use mA
type,extends(A)::B
...
endtype
endmodule
In this module, f may still be used. However, next, in module mC I will use(declare)
type(B)::Ob
and I wish "call Ob%f()" to be illegal. Or equivalently speaking, I want to ban some of the function when I extend a class.
It is hard to understand your descriiption, but if I understand it correctly it is not possible.
Consider you have a variable class(A) :: o. You are allowed to call
call o%f()
class(A) is polymorphic and can be any extended type of A so its dynamic type can be type(B). So B MUST provide publicly accessible procedure f to stay compatible with the parent.
For instance, I have a definition of type A in moduleA:
Module moduleA
implicit none
type A
private
integer::N
contains
...
procedure,pass::f=>f1
endtype
private::f1
contains
real function f1(self,x)
real::x(self%n)
end function
...
end Module
Then I found I meet a trouble when I override function f in other modules since I can not get the value of N. Even though I can have a method to get that, it seems that something like real :: x(self%get()) is impossible in the declaration. I want to keep the rule of "private" in OPP. So what choices can I have?
You cannot do that. At least in the way you describe. It would be better to see an example of the overriding to suggest other options.
The private attribute works differently in Fortran and therefore you should not directly use rules from other languages that use OOP where private means something different.
In Fortran private is about the local module, in C++ it is about the derived classes. This is very different and you cannot use the C++ (or Java, etc.) rules for private in Fortran when private in fact means something else.
To be clear, I assume you wanted this kind of overriding:
real function f2(self,x)
class(B) :: self
real::x(self%get())
end function
You than get these messages:
private.f90(15): error #8497: Illegal use of a procedure name in an expression, possibly a function call missing parenthesis. [GET]
real::x(self%get())
---------------------^
or
real::x(self%get())
1
Error: 'get' at (1) should be a FUNCTION
So the compilers will not accept a type-bound procedure in the declaration. They would accept an ordinary procedure.
This compiles in gfortran, but not in Intel Fortran. But get() must be public, which you might not want:
real function f1(self,x)
class(A) :: self
real::x(get(self))
end function
real function f2(self,x)
class(B) :: self
real::x(get(self))
end function
In ifort I get
error #8383: The dummy arguments of an overriding and overridden binding that correspond by position must have the same characteristics, except for the type of the passed object dummy arguments.
which is weird.
I have a class that looks like this:
namespace R
{
class R_Class
{
enum R_Enum
{
R_val1,
R_val2,
R_val3
}
private:
// some private stuff
public:
// some public stuff
}
}
I'm performing unit testing using an automated test tool. The compiler claims that my test harness cannot access the type R::R_Class::R_Enum.
I have no trouble accessing the values within a similar class that is defined as such:
namespace S
{
class S_Class
{
public:
enum S_Enum
{
S_val1,
S_val2,
S_val3
}
}
private:
// some private stuff
public:
// some public stuff
}
Do enums in C++ need to be given explicit visibility directives? If not given any, do they default to private? protected?
enums obey visibility in classes just like attributes, methods, nested classes or anything else. You need to make it public for outside visibility.
This is so that classes can have private enums used by its own private methods without exposing the enum values to the outside world.
All class members, enum or otherwise, are private if you don't specify otherwise. Similarly, all struct members are public if you don't specify otherwise.
If an enum needs to be public, should you nest it inside another class? I found it convenient and self-documenting to put enums in their own namespace but not another class. You treat the namespace sort of like a class name and you ignore the actual enum name. This allows you to give enum members really good names without conflicting or having to use the hungarian naming approach. In your question, for example, if we have a namespace LedState and an enum State with members On and Off, then you just use LedState::On or LedState::Off. With a typedef outside the LedState namespace, like:
typedef LedState::State LedStateType
you can ignore the actual name of the enum "State" so that name can be reused without conflict. If you need to pass an enum, you just declare it of type LedStateType. I wrote a more complete example in a recent blog entry.
An enum defined within class scope follows the access rules that applies to everything else in class scope. You need to place the enum in a public: section in order for the type to be accessible outside the class.
They don't default any different than any other member. Since private is the default, that applies to enums just as it would to any other member. Not sure why you think the behavior you're seeing has anything to do with the fact that the member is an enum.
I assumed that all class members are private by default and I was surprised to discover that structs are the exception.
Related question on SO: default visibility of C++ class/struct members
private is the default accesibility of C++ classes of classtype 'class'. If you omit specifying it, you cannot access it from the outside of your class.
How do I declare a private function in Fortran?
This will only work with a Fortran 90 module. In your module declaration, you can specify the access limits for a list of variables and routines using the "public" and "private" keywords. I usually find it helpful to use the private keyword by itself initially, which specifies that everything within the module is private unless explicitly marked public.
In the code sample below, subroutine_1() and function_1() are accessible from outside the module via the requisite "use" statement, but any other variable/subroutine/function will be private.
module so_example
implicit none
private
public :: subroutine_1
public :: function_1
contains
! Implementation of subroutines and functions goes here
end module so_example
If you use modules, here is the syntax:
PUBLIC :: subname-1, funname-2, ...
PRIVATE :: subname-1, funname-2, ...
All entities listed in PRIVATE will not be accessible from outside of the module and all entities listed in PUBLIC can be accessed from outside of the module. All the others entities, by default, can be accessed from outside of the module.
MODULE Field
IMPLICIT NONE
Integer :: Dimen
PUBLIC :: Gravity
PRIVATE :: Electric, Magnetic
CONTAINS
INTEGER FUNCTION Gravity()
..........
END FUNCTION Gravity
REAL FUNCTION Electric()
..........
END FUNCTION
REAL FUNCTION Magnetic()
..........
END FUNCTION
..........
END MODULE Field
I've never written a line of FORTRAN, but this thread about "Private module procedures" seems to be topical, at least I hope so. Seems to contain answers, at least.
jaredor summary:
The public/private attribute exists within modules in Fortran 90 and later. Fortran 77 and earlier--you're out of luck.
Private xxx, yyy, zzz
real function xxx (v)
...
end function xxx
integer function yyy()
...
end function yyy
subroutine zzz ( a,b,c )
...
end subroutine zzz
...
other stuff that calls them
...