SJWard
SJWard

Reputation: 3739

incomplete type name in nested name specifier

I have the following two classes, and I want to specify one of the methods of the second class as a friend of the first so as that method has access to it's variables. I've tried the following in my header:

class SequenceThreader;

enum MappingDirection {Nowhere, Forward, Backwards};

class SequenceMapping {
    friend void SequenceThreader::query_paths_to_fasta(std::ofstream& output_file) const;
private:
    seqID_t seq_id;
    int32_t first_seq_pos;
    int32_t last_seq_pos;
    sgNodeID_t node;
    int32_t first_node_pos;
    int32_t last_node_pos;
    int32_t matched_unique_kmers;
    uint64_t possible_unique_matches;
    uint64_t n_kmers_in_node;
    bool direction_will_continue(int32_t next_position) const;

public:
    SequenceMapping();
    bool operator==(const SequenceMapping &other);
    bool operator<(const SequenceMapping &other) const;
    friend std::ostream& operator<<(std::ostream& stream, const SequenceMapping& sm);
    void initiate_mapping(uint64_t sequence_id);
    bool ismatched();
    void start_new_mapping(const graphPosition& gpos, int32_t seqpos, const UniqueKmerIndex& counts);
    void extend(int32_t nodepos, int32_t seqpos);
    sgNodeID_t absnode() const;
    sgNodeID_t dirnode() const;
    int32_t n_unique_matches() const;
    MappingDirection node_direction() const;
    MappingDirection seq_direction() const;
    bool mapping_continues(const graphPosition& gpos) const;
    double POPUKM() const;
};

class SequenceThreader {
    typedef std::unordered_map<seqID_t, std::vector<SequenceMapping>> SequenceMappingStore;
    typedef std::unordered_map<seqID_t, std::vector<std::vector<SequenceMapping>>> SequenceMappingPathsStore;

private:
    SequenceGraph& sg;
    UniqueKmerIndex graph_kmer_index;

    uint8_t k;
    std::string query_seq_file;
    std::string output_prefix;
    uint64_t memory_limit;
    SequenceMappingStore mappings_of_sequence;
    SequenceMappingPathsStore paths_of_mappings_of_sequence;

    void map_sequences_from_file(uint64_t min_matches, const std::string& filename);
    std::set<SequenceGraphPath> all_unique_paths() const;
    void print_mapping_path_name(const std::vector<SequenceMapping>& path, std::ofstream& output_file) const;

public:
    explicit SequenceThreader(SequenceGraph &_sg, uint8_t _k = 31) : sg(_sg), k(_k), graph_kmer_index(sg, _k) {}

    void map_sequences(uint64_t min_matches, const std::string& filename, const std::string& output) {
        output_prefix = output;
        query_seq_file = filename;

        map_sequences_from_file(min_matches, filename);
    }

    void print_mappings() const;
    void mappings_paths();
    void print_paths() const;
    void graph_paths_to_fasta(std::ofstream& output_file) const;
    void query_paths_to_fasta(std::ofstream& output_file) const;
    void print_unique_paths_sizes(std::ofstream& output_file) const;
};

But I'm getting a compile error:

In file included from /Users/bward/github/bsg/src/sglib/SequenceThreader.cpp:8:
/Users/bward/github/bsg/src/sglib/SequenceThreader.h:22:17: error: incomplete type 'SequenceThreader' named in nested name specifier
    friend void SequenceThreader::query_paths_to_fasta(std::ofstream& output_file) const;

Which stumps me, since the friend declaration docs here: http://en.cppreference.com/w/cpp/language/friend

Say something like friend char* X::foo(int); // members of other classes can be friends too is fine.

What do I need to do to get this to compile?

Upvotes: 1

Views: 4505

Answers (1)

songyuanyao
songyuanyao

Reputation: 172934

SequenceThreader has to be defined firstly, only forward declaration is not enough. As the error message said SequenceThreader needs to be complete type here, otherwise the compiler can't know that SequenceThreader has such a member named query_paths_to_fasta or not.

To solve the issue you could move the definition of SequenceThreader ahead (and remove the forward declaration).

Upvotes: 3

Related Questions