いくつかのジェネリック型C
用のconst
と非const
ゲッターを持ついくつかのクラスNode
があります。
_template <typename NodeType>
class CParent{};
class Node {};
class C : public CParent<Node> {
Node& getNode(Index i);
const Node& getNode(Index i) const;
};
_
ここで、クラスgetNode
のオブジェクトに対してC
を呼び出すエイリアス関数を作成します。
_template <class CType>
NodeType& AliasGetNode(CType* cobject);
_
しかし、どうすればNodeType
を推測できますか?つまり、AliasGetNode<const C>(c)
とAliasGetNode<C>(c)
を呼び出すと、NodeType
はそれぞれ_const Node&
_と_Node&
_になります。
これどうやってするの?
_result_of
_およびdecltype
アプローチを試しましたが、成功しませんでした。
私はお勧めします:
template <class CType>
auto AliasGetNode(CType& cobject) -> decltype(cobject.getNode(0))
{
return cobject.getNode(0);
}
これはc ++ 11以降はかなり機能するはずです
コンパイラに戻り値の型を推測させます(C++ 14以降):
template <class CType>
decltype(auto) AliasGetNode(CType& cobject)
{
return cobject.getNode(0);
}
別のタイプがconst
であるかどうかに基づいて、タイプからconst
を追加/削除する単純なヘルパー特性を定義します。
template <class Src, class Dst>
using copy_const = typename std::conditional<
std::is_const<Src>::value,
const Dst,
typename std::remove_const<Dst>::type
>::type;
そしてそれを使用してください:
template <class CType>
copy_const<CType, NodeType>& AliasGetNode(CType* cobject);
C++ 14以降、関数の戻り値の型はコンパイラーによって推測される可能性があります。
_template<typename CType>
decltype(auto) AliasGetNode(CType& cobject) {
return cobject.getNode();
}
_
タイプAliasGetNode
のオブジェクトでNode
を呼び出すと、CType
はNode
に推定されます。ただし、タイプ_const Node
_のオブジェクトでAliasGetNode
を呼び出すと、CType
は_const Node
_に推定されます。
AliasGetNode
の戻り値の型をdecltype(auto)
として作成することが重要です。そうしないと、返される型の参照と定数を見逃してしまいます。
2つのエイリアス関数を作成する必要があります。1つは非constインスタンス用で、もう1つはconstインスタンス用です。
template <class CType>
const NodeType& AliasGetNode(const CType* cobject) const; // for const instance.
// The function must be const since the only difference between return type will cause redefinition error.
template <class CType>
NodeType& AliasGetNode(CType* cobject); // for non-const instance
Constと宣言されたインスタンスは、オーバーロード関数がある場合にconst関数を呼び出します。もちろん、非constインスタンスは、非constバージョンのオーバーロード関数を呼び出します。例えば:
class Aclass {
public:
string test() { return "calling non-const function"; }
string test() const { return "calling const function"; }
};
int main() {
Aclass a;
const Aclass b;
cout << a.test() << endl;
cout << b.test() << endl;
return 0;
}
結果は次のようになります。
calling non-const function
calling const function