多个非静态默认参数 C++

multiple non-static default parameters c++

本文关键字:参数 C++ 默认 静态      更新时间:2023-10-16

我正在尝试找到一种优雅的方式来声明一个启动函数,该函数使用当前存储在我的对象中的默认值(非静态值)。我基本上想做这样的事情。

class A{
    A([...], 
      string defaultName, 
      vector<string> defaultUrls, 
      map<string, string> defaultParams);
    [...]
    void initSomething(string defaultName = mDefaultName,
                  vector<string> defaultUrls = mDefaultUrls ,
                  map<string, string> defaultParams =mDefaultParams);
    private:
    string mDefaultName;
    vector<string> mDefaultUrls;
    map<string, string> mDefaultParams;
    [...]
}

我知道我可以重载initSomething()函数,但我会得到这样的东西:

void initSomething(){
    initSomething(mDefaultName, mDefaultUrls, mDefaultParams);
}
void initSomething(string defaultName){
    initSomething(defaultName, mDefaultUrls, mDefaultParams);
}
void initSomething(vector<string> defaultUrls = mDefaultUrls){
    initSomething(mDefaultName, mDefaultUrls, mDefaultParams);
}
void initSomething(map<string, string> defaultParams){
    initSomething(mDefaultName, mDefaultUrls, defaultParams);
}
void initSomething(string defaultName, vector<string> defaultUrls){
    initSomething(mDefaultName, mDefaultUrls, mDefaultParams);
}
void initSomething(string defaultName,  map<string, string> defaultParams){
    initSomething(defaultName, mDefaultUrls, defaultParams);
}
void initSomething(vector<string> defaultUrls, map<string, string> defaultParams){
    initSomething(mDefaultName, defaultUrls, defaultParams);
}
void initSomething(string defaultName,
              vector<string> defaultUrls,
              map<string, string> defaultParams);

它非常丑陋,而且如此巨大,以至于整个头文件更难阅读和掌握它的含义。

我还想到了别的事情:

void initSomething(string defaultName = "",
              vector<string> defaultUrls = vector<string>(),
              map<string, string> defaultParams = map<string, string>()){
    if (defaultName == "") {
        defaultName = mDefaultName;
    }
    if (defaultUrls.empty()) {
        defaultUrls = mDefaultUrls;
    }
    if (defaultParams.empty()) {
        defaultParams = mDefaultParams;
    }
    [...] 
}

它仍然很丑陋,并且有一个缺点,如果在调用 initSomething 函数之前成员变量未设置为空,则不会让其中一个值真正"空"。它还强制检查类的人检查方法的实现,以了解将使用成员默认值而不是空值。

我确信有一种方法,一种模式或其他东西可以做到这一点,但我还没有找到它:(

感谢您的帮助!

这是我想到的最好的。希望对您有所帮助。

#include <vector>
#include <string>
#include <iostream>
struct A{
    struct Default {};
    template <typename T>
    struct Parm{
        Parm() : gotHam(false), ham() {};
        Parm(const Default&) : gotHam(false), ham() {}
        Parm(const T& ham_) : gotHam(true), ham(ham_) {}
        operator bool(){
            return gotHam;
        }
        const bool gotHam;
        T ham;
    };
    A(std::string s_) : s(s_), i(5) {}
    void myFunction(Parm<std::string> s_ = Parm<std::string>(), Parm<int> i_ = Parm<int>()){
        std::string sValue = s_?s_.ham:s;
        int iValue = i_?i_.ham:i;
        std::cout << sValue << 't' << iValue << std::endl;
    }
    std::string s;
    int i;
};
int main() {
   A a("defaulted");
   a.myFunction(std::string("caller provided")); //caller provided  5
   a.myFunction(A::Default()); //defaulted  5
   a.myFunction(); //defaulted  5
   a.myFunction(std::string("caller provided"), 10); //caller provided  10
   a.myFunction(A::Default(), 10); //defaulted  10
}

请注意,我故意做出了一些设计决策,此代码不打算按原样使用。首先,它不处理引用参数。

您可以在此处使用代码。

不是

答案,而是我能明智地粘贴代码的唯一方法。下面是一个如何执行代码部分的示例,以便 init 将处理您想要的内容,但是参数必须按照您为函数定义声明的顺序排列,但是您可以使用一个基本函数添加简单的重载,并以一些简单和最少的大惊小怪来维护功能:

注意:下面的代码不适用于重载,因为我在 if 语句中使用了整数返回和参数,因此结果不会有任何差异,但它有助于说明原理。

#include <iostream>
#include <map>
#include <stdlib.h>
#include <sstream>
#include <vector>

using namespace std;
// this one can be private, or leave it public for versatility
int initSomething(string defaultName = "", vector<string> defaultUrls = vector<string>() , map<string, string> defaultParams = map<string, string>())
{
    int mDefaultName, mDefaultUrls, mDefaultParams = 0;
    if (defaultName == "")
        {
            //  set your default value here
            mDefaultName = 1;
        }
    if (defaultUrls == vector<string>())
        {
            //  and here
            mDefaultUrls = 2;
        }
    if (defaultParams == map<string, string>())
        {
            //  and finally here
            mDefaultParams = 3;
        }
    //  and here you can do whatever you want to do,
    //  and regardless of what form you call the one init will handle all the eventualities
    return mDefaultName + mDefaultUrls +mDefaultParams;
}
// variants
// these can be public
int initSomething()                                                     {initSomething("", vector<string>() ,map<string, string>());}
int initSomething(map<string, string>mystringmap)                       {initSomething("", vector<string>() ,mystringmap);}
int initSomething(vector<string> myvector)                              {initSomething("", myvector ,map<string, string>());}
int initSomething(vector<string> myvector, string>mystringmap)          {initSomething("", myvector ,mystringmap);}
int initSomething(string mystring)                                      {initSomething(mystring, vector<string>() ,map<string, string>());}
int initSomething(string mystring, vector<string> myvector)             {initSomething(mystring, myvector ,map<string, string>());}
int initSomething(string mystring, map<string, string>mystringmap)      {initSomething(mystring, vector<string>() ,mystringmap);}
// and so on
int main()
{
    cout << initSomething() << endl;
    return 0;
}