I'm getting a gcc warning for code which compiles fine and warning free in clang and VC++, so I assume it's something gcc specific. This is the code:
namespace myns {
using TokenList = std::vector<size_t>;
using RuleList = std::vector<size_t>;
using RulePathPair = std::pair<size_t, TokenList>;
using CandidatesCollection = struct { std::map<size_t, TokenList> tokens; std::set<RulePathPair> rules; };
class A {
private:
CandidatesCollection _candidates;
};
} // namespace myns
and the warning is:
warning: 'myns::A' has a field 'myns::A::_candidates' whose type has no linkage [-Wsubobject-linkage]
What does this mean and how to get rid of the warning?
I believe the compiler might be wrong here: the type referred to by CandidatesCollection
should in fact have external linkage.
[basic.link]/4 ...A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of
...
(4.3) — a named class (Clause 9), or an unnamed class defined in a
typedef
declaration in which the class has thetypedef
name for linkage purposes (7.1.3); ...
[dcl.typedef]/9 If the
typedef
declaration defines an unnamed class (or enum), the first typedef-name declared by the declaration to be that class type (or enum type) is used to denote the class type (or enum type) for linkage purposes only (3.5). [ Example:typedef struct { } *ps, S; // S is the class name for linkage purposes
—end example ]
Thus, if CandidatesCollection
were defined as
typedef struct { ... } CandidatesCollection;
these two passages make it clear that the class named by CandidatesCollection
would happily have external linkage.
Then there's
[dcl.typedef]/2 A typedef-name can also be introduced by an alias-declaration. The identifier following the
using
keyword becomes a typedef-name and the optional attribute-specifier-seq following the identifier appertains to that typedef-name. It has the same semantics as if it were introduced by thetypedef
specifier.
Emphasis mine. This suggests that the name introduced by using
should give the unnamed class "the name for linkage purposes" just as well as the equivalent typedef
declaration, thereby ensuring that the class has external linkage.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With