2017-01-02 6 views
3

私のプロジェクトの1つに、総称タイプTの値を含むツリーデータ構造があります。友人クラスを使用してコンパイル時間と依存性を減らす

コンパイル時間と依存性を減らすため、実装の詳細をツリーノードクラスNodeからクラスNodeImplに移動しようとしました。 Nodeの内部はプライベートであり、定義されたエントリポイント、例えばgetName機能によってのみアクセスされる必要があります。

getNameを使用することに興味のある人だけが、NodeImplをソースファイルに含める必要があります。これは私のコンパイル時間と依存性を減らすための方法です。

しかし、何らかの理由で、次の3つのおもちゃのクラスはコンパイルされません。私的なメンバーへのアクセスはないと言います。私は間違っているの?

ファイルmain.cpp

#include <iostream> 
#include "Node.h" 
#include "NodeImpl.h" 

int main(int argc, char** args) { 
    Node<int> n("Test", 2); 
    std::cout << getName(n) << std::endl; 
} 

ファイルNode.h

#pragma once 
#include <string> 

template<typename T> 
class NodeImpl; 

template<typename T> 
class Node { 
public: 
    typedef T value_type; 
    Node(const std::string& name, const T& value) : name(name), value(value) {} 

private: 
    std::string name; 
    T value; 
    friend class NodeImpl<T>; 
}; 

ファイルNodeImpl.h

#pragma once 
#include "Node.h" 

template<typename T> 
std::string getName(Node<T>& n); 

template<typename T> 
class NodeImpl { 
    NodeImpl(Node<T>& node) : mNode(node) { 
    } 
    Node<T>& mNode; 

    std::string name() { 
     return mNode.name; 
    } 

    friend std::string getName(Node<T>& n); 
}; 

template<typename T> 
std::string getName(Node<T>& n) { 
    auto x = NodeImpl<T>(n); 
    return x.name(); 
} 
+5

友人の友人はあなたの友人ではありません – Danh

+0

助けてくれてありがとう。もちろん、友人宣言は推移的ではありません。私は 'NodeImpl.h'を変更しました。これが解決策だと思った。しかし、まだそれはコンパイルされていません。 :-( – Aleph0

答えて

2

warning produced by GCCは、洞察力を与える:

言い換えれば
warning: friend declaration 'std::__cxx11::string getName(Node<T>&)' declares a non-template function [-Wnon-template-friend] 
friend std::string getName(Node<T>& n); 
            ^
note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) 

、あなたのクラスNodeImpl<int>T = intのための関数テンプレートtemplate <class T> std::string getName(Node<T> &)からインスタンス化機能std::string getName<int>(Node<int> &)とは無関係なグローバル関数std::string getName(Node<int> &)を、befriendingました。

だから、正しい解決策はこれです:

template<typename T> 
class NodeImpl { 
    // ... as before ... 

    friend std::string getName<T>(Node<T>& n); 
}; 

この[live example]は、このソリューションが実際に機能することを示しています。

+0

これはとても驚きです。私はVisual Studioを使用しています。 – Aleph0

関連する問題