2017-11-12 5 views
2

ように私はこのコードのサンプルブロックを持っている:置きsetw()変数

#include <iostream> 
#include <iomanip> 
#include <string> 
using namespace std; 

int main(){ 
    string blank = " "; 
    cout << "Hello" << blank << "47"; 
} 

私は私の元のコードでは、このタイプのCOUT年代の多くを持っています。 空白の文字列をsetw(2)に変更することができます。私は自分のコードに含まれているすべての文字に対してsetw(2)と空白を置き換える必要はありません。 cpp関数を変数に設定する方法はありますか? 名前を入力して関数を呼び出すことはできますか?例えば :

func blank = setw(2); 
cout<< "Hello" << blank << "47"; 
+3

['using namespace std;'は悪い習慣です(https://stackoverflow.com/q/1452721/2176813)、絶対に使用しないでください。 – tambre

+1

'#define blank std :: setw(2)'? –

+2

なぜ私はこの質問を閉じるのに2つの票があるのか​​わかりません、なぜならそれは "不明"です。どのように不明ですか? – Galik

答えて

9

std::setw(x)のタイプはunspecifiedですが、それを知る必要はありません。

あなただけautoを使用することができます。

auto blank = std::setw(2); 

@StoryTellerが指摘したように、このはまともな実装で仕事、それが保証されていないべきです。

より安全なオプションが過負荷に<<でクラスを作るために次のようになります。

struct blank_t {} blank; 

std::ostream &operator<<(std::ostream &s, blank_t) 
{ 
    return s << std::setw(2); 
} 
+0

私は "auto"についてより多くの情報を得ようとしていますが、何を検索するのか分からず、 "auto"タイプですか?または演算子?両方が間違っていると推測します。 – Shayan

+2

'auto'はコンパイラがあなたのために型を見つけ出す要求です。ドキュメントリンク:http://en.cppreference。 – user4581301

+1

@Shayan - 正式には[プレースホルダ型指定子](http://en.cppreference.com/w/cpp/language/auto)として知られています。 – StoryTeller

3

std::setwはマニピュレータです。その型は指定されておらず、実装固有です。

これで変数にcpp関数を設定する方法はありますか?

C++ 11では、、特にstd::functionを使用できます。また、lambda expressionsもあります。

私はあなたのケースでそれを使いたいとは思わない。

source code editorを学ぶこと。 blankのすべてのオカレンスを適切なもの、つまりstd::setw(2) ...に置き換えてください。これによりコードが読みやすくなります。優れた編集者は簡単にそれを行うことができます。

あなたはpreprocessorを乱用し、

#define blank setw(2) 

しかし悪い考え(コードが読めないままであるので)であるあなたのケースで可能性があります。 autoanswered by HolyBlackCatとして使用しても、コードを判読できず混乱させることがあります。

コードは書かれたよりずっと頻繁に読み込まれます。読みやすいようにしてください(数週間であなた自身でさえ)。

膨大な(100万行の)プロジェクトがある場合は、そのような場合にソースコードを変更するためのスクリプトを書くのに数分かかります。 (emacsスクリプト可能エディタであるため)GNU emacsと簡単です。

1

代替ソリューションは、その唯一の目的カプセル化された参照先オブジェクトのオーバーロードされたoperator<<を提供することで、小さなラッパークラスを記述することです。そのクラスをテンプレート化することで、最初にstd::ostreamにフィードできるすべてのものを処理できます。ここで

は一例です:

#include <iostream> 
#include <iomanip> 
#include <string> 

template <class T> 
struct Blank { 
    Blank(T const& t) : t(t) {} 
    T const& t; 
}; 

// utility function so that you can use type deduction at the call site: 
template <class T> 
Blank<T> blank(T const& t) { 
    return Blank<T>(t); 
} 

template <class T> 
std::ostream& operator<<(std::ostream& os, Blank<T> const& blank) { 
    os << std::setw(2) << blank.t; 
    return os; 
} 

int main() { 
    std::cout << "Hello" << blank("4") << blank(7) << blank(std::string("8")) << '\n'; 
} 

それはあなたが求めてきました、正確な構文ではありませんが、それはかなり近づきます。

はまた、(その後、あなたは未定義の動作を持っていると思いますのでによるダングリング参照に)それがoperator<<で使用される前何のカプセル化されたオブジェクトが破棄されていないことを確認する必要があり、それはBlankオブジェクトを命名しない作成決してならば実現するのは簡単です。