2017-09-09 5 views
2

コード例に示すテンプレートクラスを使用して、間違った引数や引数を間違った順序で渡したり、引数の意味を文書化できないような新しい型を作ります。コード例のnumber(2)を参照してください。参照縮退によるあいまいなオーバーロード

しかし、少し厄介なものがあります。このクラスは参照型(コード例の番号(3)を参照)に使用できません。もちろん、それは動作しません。参照の崩壊が私のコンストラクタをあいまいにしているので、例を実現するためにT & &コンストラクタ(コード例の番号(1)を参照)を無効にしたのです。しかし、それは - 私は望む - 次善策だけですか?

質問:StrongTypeクラスを使用する方法はありますか?参照型に対してのみStrongTypeRefのような特別なクラスを作成せずに、非参照型の場合は両方のコンストラクタを保持しますか?

例はそのままコンパイルされます。 エラーを表示するには、コメントを外してnumber(1)を有効にしてください。

Thxを事前に入力してください。

#include <iostream> 

template <typename T, typename Parameter> 
class StrongType 
{ 
public: 
    explicit StrongType(T const& value) : value_(value) {} 
    // (1) explicit StrongType(T&& value) : value_(value) {} 
    T& get() { return value_; } 
    T const& get() const {return value_; } 
private: 
    T value_; 
}; 

// (2) works great 
using Iteration = StrongType<int, struct IterationType>; 

// (3) Not o.k. 
using IterationRef = StrongType<int&, struct IterationRefType>; 

void do_something1(Iteration k) 
{ 
    std::cout << k.get(); 
} 

void do_something2(IterationRef k) 
{ 
    k.get() = 42; 
} 

int main(int argc, const char * argv[]) { 
    Iteration it1(5); 
    do_something1(it1); 

    int refed = 0; 
    IterationRef it2(refed); 
    do_something2(it2); 
    return 0; 
} 
+0

を私はあなたのStrongTypeは超短いですので、そのままで、これは超魅力的ではありません意味。はるかに長い本物ですか?また、このサンプルは私のためにコンパイルします、あなたはコンパイルエラーを得るリンクを投稿できますか? –

+0

@NirFriedman申し訳ありません。私は質問に明確化を加えました。 – DrSvanHay

答えて

2

あなたは完璧な転送を使用する場合、それは動作します:

template <typename T, typename Parameter> 
class StrongType 
{ 
public: 
    template <class U> 
    explicit StrongType(U&& value) : value_(std::forward<U>(value)) {} 
    T& get() { return value_; } 
    T const& get() const {return value_; } 
private: 
    T value_; 
}; 

ライブ例:http://coliru.stacked-crooked.com/a/a78cb4617961f3c9

2

1つの解決策は、単にそれを専門化することです。ただ、あいまいなコンストラクタなしで専門を追加します。

template <typename T, typename Parameter> 
class StrongType<T &, Parameter> 
{ 
public: 
    explicit StrongType(T const& value) : value_(value) {} 
    T& get() { return value_; } 
    T const& get() const {return value_; } 
private: 
    T value_; 
}; 

これは正式に作成し、テンプレートパラメータに基づいて別のテンプレートを使用せずに、コンパイルエラーを修正します。これはまさに専門分野のためのものです。ただし、これはすべての問題に対処する場合とそうでない場合があります。たとえば、専門化のvalue_クラスメンバーは、ではなく、となります。これは、あなたが起こりたいことかもしれません。必要に応じて微調整します。

あなたのお問い合わせは、コンパイルエラーを解決することに限定されています。このようなブルー​​トフォースの解決策は、小さくてシンプルなクラスでは問題ありません。基本テンプレートがより複雑な場合は、プレーンな専門化によって、もちろんコードが膨らんでいきます。その場合、いくつかのリファクタリングが必要になります。

関連する問題