我發現有時函數有很多參數。這些參數中的很多參數都是可選的,有時候一組這些選項通常來自單個其他對象(所以最終你會做到foo(Object.GetN(), Object.GetM(), Object.GetK())
)。對付它的常用方法是創建不同的情況不同的重載,它可能被稱爲:這個方法已經有了名字嗎?
foo(int n, int m, int k /*, and on and on*/);
foo(bool b, int m/*, ...*/);
foo(int m, int k/*, ...*/);
foo(Object_t object/*, ...*/);
//...
這裏的問題是,它的參數是不是特別直觀,你可以得到相當的驚喜,當你稱之爲你想要的超負荷。
最近我有一個想法,讓它更容易讓函數調用正確,讓我自己在處理這些具有多種被調用方法的函數時更容易。這個解決方案並沒有涵蓋所有可能的需求,但它對我來說效果很好。
而不是創建一切的重載,我會創建一個函數,只需要可變數量的參數,然後提取可能的參數在函數內使用。至於參數,我會將它們包裝在爲這些函數創建的輔助類中。這將允許用戶聲明每個整數,布爾值或字符串或者什麼意思,而不是依賴函數簽名中的位置信息。
代替foo(n, m)
(其中由變量的名稱會以上建議可能的錯誤),你會打電話foo(OptN(n), OptM(m))
使得它完全清楚每個參數將被用於和更難有一個參數被誤解。
如果任何人對這種可能的實現感興趣,我將在最後包含一個MCVE。
我從來沒有見過或聽說過這種技術,但我也很難相信我是第一個想到它的人。所以,最後,我的問題僅僅是這個技術有沒有名字?
如果它沒有名稱,我一直在調用這些函數的聲明函數,因爲你聲明每個參數明確代表的是什麼,而不是依賴於參數賦予其含義的位置函數。
MCVE:
#include <iostream>
#include <utility>
struct Option1
{
Option1(bool b):b(b){}
bool b;
bool operator()() const {return b;}
};
struct Option2
{
Option2(int n):n(n){}
int n;
int operator()() const {return n;}
};
struct Group : Option1, Option2
{
Group(bool b, int n):Option1(b), Option2(n){}
};
/*
* Get the option from what the user gave us.
*/
template <class OptionType, class OptionsGetter, class RType>
auto GetOptionImpl(const OptionsGetter & options_getter,
const RType&, std::true_type) ->
decltype(((const OptionType&)options_getter)())
{
return ((const OptionType&)options_getter)();
}
/*
* Get the default value specified since the user didn't pass
* in that option
*/
template <class OptionType, class OptionsGetter, class RType>
RType GetOptionImpl(const OptionsGetter&, const RType & d, std::false_type)
{
return d;
}
/**
* Returns the value of the option OptionType if the user
* passed that in (inside OptionsGetter) and returns the
* default value if they didn't pass it in.
*/
template <class OptionType, class OptionsGetter, class RType>
auto GetOption(const OptionsGetter & oOptionsGetter,
const RType & oDefault) ->
decltype(std::declval<OptionType>()())
{
return GetOptionImpl<OptionType>(oOptionsGetter, oDefault,
std::is_base_of<OptionType, OptionsGetter>());
}
template <class ... Params>
void foo(Params ... params)
{
struct ParamsGetter : Params...
{
ParamsGetter(Params ... p): Params(p)...{}
} params_getter(params...);
if(GetOption<Option1>(params_getter, false))
std::cout << "Option 1 was true ";
else
std::cout << "Option 1 was false ";
std::cout << "Option 2: " << GetOption<Option2>(params_getter, 3) << '\n';
}
int main()
{
foo(Option1{true}, Option2{22});
foo();
foo(Option2{1});
foo(Group(true, 2));
}
輸出:
Option 1 was true Option 2: 22
Option 1 was false Option 2: 3
Option 1 was false Option 2: 1
Option 1 was true Option 2: 2
不明白爲什麼你需要所有的東西.... – jpo38
這是你在尋找什麼? https://en.wikipedia.org/wiki/Named_parameter –
你可以使用我在這裏描述的技術獲得相同的結果:http://stackoverflow.com/questions/40381918/preferred-mechanism-to-attach-a-類型到標量 –