2016-03-23 9 views
4

名前のないパラメータを使用して、単純な型のディスパッチャを作成していましたが、これはかなり普通のことです。一時変数を作成せずに名前のないパラメータを「渡す」ことは可能ですか?

実際に関数を呼び出すときは、変数を手に入れずにオーバーロードを取りたいと思っていました。出来ますか?

など。

void f1(int /*can change the type*/) { 
} 
int main(int, char*) { 
    f1(/*what to put here?*/); 
    return 0; 
} 

私の「本当の」例は単純なタイプベースのディスパッチャーでした。ベストは、名前のパラメータとしてポインタだったと私が思いついたものを、私はそれが少なくともオーバーヘッド可能性があると思う:

#include <iostream> 
using namespace std; 

template<typename U> 
class A { 
public: 

A(const U& u) : u(u) {}; 

template <typename T> 
T get_as() { 
    T* t; // <- ugly 
    return get(t); 
} 

U get(U*) { 
    return u; 
} 

int get(int*) { 
    return i; 
} 

double get(double*) { 
    return d; 
} 

private: 
    U u; 
    int i = 5; 
    double d = 3.14; 
}; 

int main() { 
    A<string> a("name"); 
    cout << a.get_as<double>() << '\n'; 
    cout << a.get_as<int>() << '\n'; 
    cout << a.get_as<string>() << '\n'; 
    return 0; 
} 

私はそれはおそらく、最適化されますので、それは、ポインタで純粋に審美的だと思うが、それでも私は疑問に思います。私も、これは不可能かもしれないと思います。なぜなら、(AFAIK)この議論が積み重なるからです。技術的には常にこの「オーバーヘッド」があります。これは正しいですか?

これが別の質問であるべきかどうかはわかりませんが、トリッキーなことで「このオーバーロードを拾うだけです」と表現する方法はありますか?

PS。私はT*(0)を「醜い」行に使うことができると考えましたが、それはおそらく読みにくいでしょう。

+0

無名のパラメータは合法ですが、いくつかの特定の用途にすぎません:http://stackoverflow.com/questions/12186698/on-unnamed-parameters-to-functions-c – Baronz

+0

@KerrekSB私の悪いです。私はもちろんパラメタを意味していました。編集されました。うまくいけばうまくいきます。 – luk32

+0

@ luk32:ありがとう、はるかに明確です。 –

答えて

6

あなたは空のタグ構造体を渡すよりも、任意の明確またはより効率的に取得することはできません。

template<class T> struct tag {}; 

double get(tag<double>) { 
    return d; 
} 

template <typename T> 
T get_as() { 
    return get(tag<T>{}); 
} 

派遣のためのポインタ型を使用してオーバー利点が誤って渡されたNULLポインタをindirectingの危険がありませんということです。

(脇:What happens to empty classes in the AMD64 ABI? - しかし、あなたの呼び出しは通常、インライン化されます)

+0

ハ!すごくいいですね。これに標準で何かがあるかどうか知っていますか?たくさんのヘルパー構造テンプレートがあります。だから、おそらく 'タグを定義する必要はありません。 – luk32

+0

@ luk2私は恐れていません。標準にはいくつかのタグがありますが、具体的には(http://en.cppreference.com/w/cpp/iterator/iterator_tags)、タイプメタ機能はタグとして使用できますが、実際にはその目的のために設計されていません。独自のタグクラステンプレートを使用する利点は、自由な関数呼び出しを修飾する必要がないように、ADLパラメータとして2つの役割を果たすことができるということです。 – ecatmur

1

あなたは、これはあなたを助ける可能性がある場合、私は思ったんだけど、 "美学" について話しているので:

Live Demo

template<typename U> 
class A 
{ 
public: 
    static_assert(!std::is_same<int, U>::value && !std::is_same<double,U>::value, 
           "Template argument cannot be <int> or <double>."); 
    A(const U& u) : u(u) {}; 
    explicit operator U() { return u; } 
    explicit operator int() { return i; } 
    explicit operator double() { return d; } 

private: 
    U u; 
    int i = 5; 
    double d = 3.14; 
}; 

int main() 
{ 
    A<string> a("wow"); 
    cout << double(a) << '\n'; 
    cout << int(a) << '\n'; 
    cout << string(a) << '\n'; 
    return 0; 
} 

私は、ユーザー定義変換演算子が明示的であれば邪悪ではないと思います。

「間違って」使用することはできません。また、このクラスにはオーバーヘッドがありません。

+0

これはいいですが、ユースケースは少し異なります。メンバーを返すための一般的な方法が必要です。それは意味的には少し異なりますが、近いですが。コンバートで元のオブジェクトが失われた場合、問題はこれがコンクリートメンバを変換した汎用関数に渡されたということでした。もともと私の問題ではありませんでした。オーバーロードされた 'set'がありました。これは簡単で、' get'のオーバーロードが望まれました。たぶん 'get_as'は少し誤解を招くかもしれません。 'get_me 'のようなものは、' get_me '、' get_me 'のように良いでしょう。 'static_assert'のための小道具 – luk32

関連する問題