2017-07-22 4 views
0

考慮する: - タイプの値または(すでに)参照型のいずれか要するにC++ SFINAEは参照型と参照型に変換された引数の間のオーバーロードを選択しますか?

struct BigData {...}; 

// Let's get a BigData by reference, but use it as a value. 
// For example, we may want to make a copy of the object, but we'd 
// like to avoid the pass-by-value overhead at the call site. 
template <typename T, *some template magic?*> 
void processData(T& t) { 
    printf("Your BigData was converted to a reference argument.\n"); 
    ... 
} 

// Now, we want an overload that will know that there wasn't a 
// conversion to reference and will treat it like a reference. 
// Perhaps we are adding this BigData to a list of references. 
template <typename T, *some template magic?*> 
void processData(T& t) { 
    printf("You gave me a BigData reference.\n"); 
    ... 
} 

int main() { 
    BigData data; 
    BigData& ref = data; 

    processData(data); // "Your BigData was converted to a reference argument." 
    processData(ref); // "You gave me a BigData reference." 

    return 0; 
} 

を、私の目的は、結合基準がどこから来たかを区別オーバーロードを持つことです。私はstd::enable_ifを使用して試してみましたが、ファミリは、Tへの参照をしていないオーバーロードと組み合わせて使用​​しましたが、これを達成する方法が見つかりません。どんな助けでも大歓迎です!

答えて

3

リファレンスバインディングの仕組みを理解していないと思います。あなただけが参照によってBigDataオブジェクトを渡したい場合は、あなただけの次

を行う必要があるので、別の参照を参照するだけでなく、値型である値(すなわち修飾参照しない)

をバインドすることはできません

template <typename T> 
void processData(T& t) { 
    cout << "Your BigData was passed as a reference argument" << endl; 
    // ... 
} 

int main() { 
    BigData data; 
    BigData& ref = data; 

    processData(data); 
    processData(ref); 

    return 0; 
} 

ここで、processDataの両方の呼び出しでは、BigDataオブジェクトが参照渡しされます(つまり、関数呼び出し時にはコピーされません)。

関数に渡されるオブジェクトが通常の場合とは別に参照される場合に対処する必要はありません。 std::enable_ifはここでは必要ありません。

さらに2つの場合を区別する方法はありません。どちらも左辺値なので、関数の引数としてdataまたはrefを使用します。あなたは、式のdecltypeが参照またはない

#include <iostream> 
#include <type_traits> 

using std::cout; 
using std::endl; 

template <typename T, std::enable_if_t<std::is_reference<T>::value>* = nullptr> 
void processData(std::add_lvalue_reference_t<T>) { 
    cout << "You gave me a reference argument." << endl; 
} 

template <typename T, std::enable_if_t<!std::is_reference<T>::value>* = nullptr> 
void processData(std::add_lvalue_reference_t<T>) { 
    cout << "Your argument was converted to a reference." << endl; 
} 

int main() { 
    auto integer_value = 1; 
    const auto& integer_ref = 2; 
    processData<decltype(integer_value)>(integer_value); 
    processData<decltype(integer_ref)>(integer_ref); 

    return 0; 
} 
+0

右であるかどうかを検査する場合は、次のような何かをする必要があります。しかし、私の目的は、バインディングがどこから来たのか(型の値か(既に)参照型のどちらか)を区別するオーバーロードを持つことです。 –

+0

@BrandonKammerdienerは更新された答えを見てください – Curious

+0

ありがとうございます。これは私の知る限りではありますが、理想的には電話を変更しないようにしたいと思います。私はあなたの助けに感謝します! –

関連する問題