在C++ 03,則具有不同的可能性:
- 生成0-N的參數(使用Boost.Preprocessor例如)
- 使用缺點-列表(
cons(1)("some string")(foo)
)
- 使用重載對象和重載一些運營商(
operator()
例如,或operator%
等Boost.Format庫)
第一個選項是有點麻煩,感覺,因爲不是每個人都可以很容易地理解宏,所以如果您計劃儘快遷移到C++ 0x,我只會保留它以用於短期解決方案。
第三個選項可能會提供一個很好的自定義觸摸(格式是用多種語言的%
符號完成的),但這也意味着需要記住每次這個特定的「可變參數」函數是如何工作的。
我個人的偏好是cons
方法,因爲它解決了兩個問題:
- 的定義只涉及模板,所以它是更具可讀性和超過1 maintanable。
- 您定義的利弊,機械一次,你可以重新使用它的任何「可變參數」功能(和他們保持功能),所以它是比較一致的,並保存你的工作
例如,這裏是如何可以工作:
的包括本例中將使用:
#include <cassert>
#include <iostream>
#include <string>
一種結果類型附加價值的助手(也可能是與預謀更有效,但這將意味着通過以相反的順序論點是反直覺):
template <typename T, typename Next> struct Cons;
struct ConsEmpty;
template <typename Cons, typename U>
struct cons_result;
template <typename U>
struct cons_result<ConsEmpty, U> {
typedef Cons<U, ConsEmpty> type;
};
template <typename T, typename U>
struct cons_result<Cons<T, ConsEmpty>, U> {
typedef Cons<T, Cons<U, ConsEmpty> > type;
};
template <typename T, typename Next, typename U>
struct cons_result<Cons<T, Next>, U> {
typedef Cons<T, typename cons_result<Next, U>::type> type;
};
的Cons
模板本身,附魔operator()
附加價值。請注意,它與不同類型創建一個新的項目:
template <typename T, typename Next>
struct Cons {
Cons(T t, Next n): value(t), next(n) {}
T value;
Next next;
template <typename U>
typename cons_result<Cons, U>::type operator()(U u) {
typedef typename cons_result<Cons, U>::type Result;
return Result(value, next(u));
}
};
struct ConsEmpty {
template <typename U>
Cons<U, ConsEmpty> operator()(U u) {
return Cons<U, ConsEmpty>(u, ConsEmpty());
}
};
template <typename T>
Cons<T, ConsEmpty> cons(T t) {
return Cons<T, ConsEmpty>(t, ConsEmpty());
}
一個重新VarPrint
它:
bool VarPrint(std::ostream& out, const std::string& s, ConsEmpty) {
std::string::size_type offset = 0;
if((offset = s.find("%")) != std::string::npos) {
if(offset == s.size() - 1 || s[offset + 1] != '%') {
assert(0 && "Missing Arguments!");
return false;
}
}
out << s;
return true;
}
template<typename T, typename Next>
bool VarPrint(std::ostream& out,
std::string const& s,
Cons<T, Next> const& cons)
{
std::string::size_type prev_offset = 0, curr_offset = 0;
while((curr_offset = s.find("%", prev_offset)) != std::string::npos) {
out << s.substr(prev_offset, curr_offset);
if(curr_offset == s.size() - 1 || s[curr_offset + 1] != '%') {
out << cons.value;
if(curr_offset + 2 < s.length())
return VarPrint(out, s.substr(curr_offset + 2), cons.next);
return true;
}
prev_offset = curr_offset + 2;
if(prev_offset >= s.length())
break;
}
assert(0 && "Extra Argument Provided!");
return false;
}
而且演示
int main() {
VarPrint(std::cout, "integer %i\n", cons(1));
VarPrint(std::cout, "mix of %i and %s\n", cons(2)("foo"));
}
您可以檢查ideone的輸出:
integer 1
mix of 2 and foo
如果你想要任意數量的參數,它是不可能的。你所能做的就是爲一些綁定的參數提供實現,比如1-10個參數。 – Dani
編譯你的例子:'prev_offset> = s.length' - >注意缺少'()'來調用'length'函數:) –
謝謝。我錯過了'()',而直接輸入。哈:D – winnerrrr