C++ 函数参数分组与常量

C++ 函数参数分组与常量,c++,templates,constants,C++,Templates,Constants,我们正在尝试重构我们的代码,我们想要的改进之一是:许多函数有许多参数,但它们中的许多共享一个共同的子集。因此,我们想创建一个结构,将它们分组。问题是,有些函数需要一些参数为常量,而有些参数不是常量。其中一些函数必须能够调用提供此参数分组结构的这些函数的子集,但受到以下限制:被调用函数不能“降低”此结构的常数(请参见以下示例)。实现此结构所需的所有变体可以解决问题,但并不优雅。我们正在研究的一个解决方案是使用模板,例如: template<class A, class B, class C&

我们正在尝试重构我们的代码,我们想要的改进之一是:许多函数有许多参数,但它们中的许多共享一个共同的子集。因此,我们想创建一个结构,将它们分组。问题是,有些函数需要一些参数为常量,而有些参数不是常量。其中一些函数必须能够调用提供此参数分组结构的这些函数的子集,但受到以下限制:被调用函数不能“降低”此结构的常数(请参见以下示例)。实现此结构所需的所有变体可以解决问题,但并不优雅。我们正在研究的一个解决方案是使用模板,例如:

template<class A, class B, class C>
struct my_container
{
    A a;
    B b;
    C c;
};

void foo1(my_container<int, char, float const> & my_cont)
{
}

void foo2(my_container<int const, char, float const> & my_cont)
{
    // This should NOT be allowed: we do mind something being const to be treated by the
    // called function as non-const.
    foo1(my_cont);
}

void foo3(my_container<int, char, float> & my_cont)
{
    // This should be allowed: we don't mind something being non-const to be treated by the
    // called function as const.
    foo2(my_cont);
}
模板
构造我的容器
{
A A;
B B;
C C;
};
void foo1(我的容器和我的容器)
{
}
void foo2(我的容器和我的容器)
{
//这是不允许的:我们确实介意某些东西被认为是常量,由
//函数被称为非常量。
foo1(我的继续);
}
void foo3(我的容器和我的容器)
{
//这应该是允许的:我们不介意一些非常量的东西被
//将函数称为常量。
foo2(我的继续);
}

我们的问题是,foo2调用foo1时编译器没有抱怨,我们希望完全相反。这甚至可以用模板实现吗?还有其他技术吗?

两者都不应该起作用。模板的不同实例化是 未引用的类型,它们之间没有隐式转换。所以
my\u container
my\u container
my\u container
都是不相关的 类型之间没有隐式转换

应该可以使用继承,使用 元编程技巧来确定您从中继承了什么,但我不是
当然是这样,我怀疑这将是比它的价值更大的努力

我的解决方案有点元编程。看起来很难看,没有经过全面测试,但无论如何: 这样,一切都应该“开箱即用”

#包括
#包括
模板
构造我的容器
{
A A;
B B;
C C;
模板
操作员my_容器&()
{
/*首先,检查是否兼容*/
BOOST_STATIC_ASSERT((BOOST::is_same::value));
BOOST_STATIC_ASSERT((BOOST::is_same::value));
BOOST_STATIC_ASSERT((BOOST::is_same::value));
/*强制执行*/
BOOST_STATIC_ASSERT(!BOOST::is_const::value | | BOOST::is_const::value);
BOOST_STATIC_ASSERT(!BOOST::is_const::value | | BOOST::is_const::value);
BOOST_STATIC_ASSERT(!BOOST::is_const::value | | BOOST::is_const::value);
return*reinterpret\u cast(此项);
}
};
void foo1(我的容器和我的容器)
{
}
void foo2(我的容器和我的容器)
{
//这是不允许的:我们确实介意某些东西被认为是常量,由
//函数被称为非常量。
//foo1(我的继续);///BOOST\u STATIC\u断言失败!万岁!
}
void foo3(我的容器和我的容器)
{
//这应该是允许的:我们不介意一些非常量的东西被
//将函数称为常量。
foo2(我的继续);///没有抱怨!万岁!
}
int main(int argc,char*argv[])
{
我的食物吧;
foo3(foobar);
返回0;
}

在不涉及未定义行为的情况下,这可以通过另一个间接级别来实现。添加引用原始成员的视图类。常量可以隐式添加,但不能删除

template<class A, class B, class C>
struct my_container
{
    A a;
    B b;
    C c;
};

template <class A, class B, class C>
class my_container_view
{
    A* a_;
    B* b_;
    C* c_;

public:
    template <class A_, class B_, class C_>
    my_container_view(my_container<A_, B_, C_>& source):
        a_(&source.a), b_(&source.b), c_(&source.c)
    {}
    template <class A_, class B_, class C_>
    my_container_view(my_container_view<A_, B_, C_>& source):
        a_(&source.a()), b_(&source.b()), c_(&source.c())
    {}
    A& a() const { return *a_; }
    B& b() const { return *b_; }
    C& c() const { return *c_; }
};

void foo1(my_container_view<int, char, float const> my_cont)
{
    my_cont.a() = 10;
    my_cont.b() = 'a';
    my_cont.c() /*= 3.14*/;
}

void foo2(my_container_view<int const, char, float const> my_cont)
{
    my_cont.a() /*= 10*/;
    my_cont.b() = 'a';
    my_cont.c() /*= 3.14*/;

    //foo1(my_cont); //not allowed
}

void foo3(my_container_view<int, char, float> my_cont)
{
    my_cont.a() = 10;
    my_cont.b() = 'a';
    my_cont.c() = 3.14;
t
    foo2(my_cont);
}

int main()
{
    my_container<int, char, float> mc;
    foo1(mc);
    foo2(mc);
    foo3(mc);
}
模板
构造我的容器
{
A A;
B B;
C C;
};
模板
将“我的容器”视图分类
{
A*A;
B*B_;
C*C;
公众:
模板
我的容器视图(我的容器和源):
a_uu(&source.a)、b_u(&source.b)、c_u(&source.c)
{}
模板
我的容器视图(我的容器视图和源):
a_u(&source.a()),b_u(&source.b()),c_u(&source.c())
{}
A&A()常量{return*A}
B&B()常量{return*B_;}
C&C()常量{return*C_;}
};
void foo1(我的\u容器\u查看我的\u cont)
{
my_cont.a()=10;
my_cont.b()=“a”;
my_cont.c()/*=3.14*/;
}
void foo2(我的\u容器\u查看我的\u cont)
{
my_cont.a()/*=10*/;
my_cont.b()=“a”;
my_cont.c()/*=3.14*/;
//foo1(my_cont);//不允许
}
void foo3(我的\u容器\u查看我的\u cont)
{
my_cont.a()=10;
my_cont.b()=“a”;
my_cont.c()=3.14;
T
foo2(我的继续);
}
int main()
{
my_容器mc;
foo1(mc);
foo2(mc);
foo3(mc);
}

(不过,我怀疑这值多少钱。通常情况下,对于类,要么你可以修改它的所有成员——你只是不修改你不想修改的成员,要么你不能修改任何成员。如果你想要这种级别的控制,你宁愿分别传递每个参数——这与你正在做的相反。)

你是对的,不过,我还是很快对它进行了测试。正如预期的那样,两者都不能在g++4.4中工作。或者MSVC 2010。在我看来,如果常数单独变化,也许只是不要尝试将这些参数分组。模板似乎表明您试图将三个不相关的值组合在一起?-如果你有一个真正的相关功能类,我不认为人们通常会试图使它部分可修改。例如,不允许函数只修改点实例的x坐标而不修改y坐标。如果这很重要,我想你会把它们作为单独的论点来传递。我想知道你的解决方案与我的相比有什么好处,除了你的解决方案不需要推进之外?关于你的评论,我认为OP在问题的前两句话中清楚地说明了他的用例。@zerm:我怀疑这种在技术上不相关的类型之间进行的重新解释是技术上未定义的行为,尽管我不明白为什么它在实践中不起作用。-至于疑问:“问题是有些函数需要一些参数是常量,而有些参数不是常量
template<class A, class B, class C>
struct my_container
{
    A a;
    B b;
    C c;
};

template <class A, class B, class C>
class my_container_view
{
    A* a_;
    B* b_;
    C* c_;

public:
    template <class A_, class B_, class C_>
    my_container_view(my_container<A_, B_, C_>& source):
        a_(&source.a), b_(&source.b), c_(&source.c)
    {}
    template <class A_, class B_, class C_>
    my_container_view(my_container_view<A_, B_, C_>& source):
        a_(&source.a()), b_(&source.b()), c_(&source.c())
    {}
    A& a() const { return *a_; }
    B& b() const { return *b_; }
    C& c() const { return *c_; }
};

void foo1(my_container_view<int, char, float const> my_cont)
{
    my_cont.a() = 10;
    my_cont.b() = 'a';
    my_cont.c() /*= 3.14*/;
}

void foo2(my_container_view<int const, char, float const> my_cont)
{
    my_cont.a() /*= 10*/;
    my_cont.b() = 'a';
    my_cont.c() /*= 3.14*/;

    //foo1(my_cont); //not allowed
}

void foo3(my_container_view<int, char, float> my_cont)
{
    my_cont.a() = 10;
    my_cont.b() = 'a';
    my_cont.c() = 3.14;
t
    foo2(my_cont);
}

int main()
{
    my_container<int, char, float> mc;
    foo1(mc);
    foo2(mc);
    foo3(mc);
}