通过以前的答案,我觉得我可能有设计问题,但即使答案是学术性的,我仍然想知道是否有可能。我已经用Python编程了一段时间,它显示了。我正在尝试在对象上创建类似setattr
访问权限的内容。用手看起来像:
template<class T, class U>
void set_parameter_sigma(T &S, U val) {
for(auto &x: S) { x.sigma = val; }
}
template<class T, class U>
void set_parameter_epsilon(T &S, U val) {
for(auto &x: S) { x.epsilon = val; }
}
template<class T, class U>
void set_parameter_length(T &S, U val) {
for(auto &x: S) { x.length = val; }
}
我想要的是看起来像下面的伪代码:
template<class T, class U, class N>
void set_parameter(T &S, U val) {
for(auto &x: S) { x.N = val; }
}
我可以像set_parameter(foo, 2.0, "epsilon")
一样调用它,编译器会自动创建set_parameter_epsilon
函数。虽然我确信提升可以做到这一点,但如果可能的话,我更愿意看到仅限STL的版本。
答案 0 :(得分:5)
哎呀原来我错过了要求来循环setter中的容器元素。那么,让我修改我的错误:
#include <utility>
template <class C, class U, class U2 /* assignable from U*/,
class T = typename C::value_type>
void set_parameter(C& container, U&& val, U2 (T::* pmember), typename C::value_type* sfinae=nullptr)
{
for (auto& instance : container)
(instance.*(pmember)) = std::forward<U>(val);
}
#include <iostream>
#include <string>
#include <vector>
struct X
{
double foo;
std::string splurgle;
};
int main()
{
std::vector<X> xs(10);
set_parameter(xs, 42, &X::foo);
set_parameter(xs, "hello world", &X::splurgle);
for (auto const& x : xs)
std::cout << x.foo << ", " << x.splurgle << "\n";
}
打印哪些内容( Live on Coliru )
42, hello world
42, hello world
42, hello world
42, hello world
42, hello world
42, hello world
42, hello world
42, hello world
42, hello world
42, hello world
#include <utility>
#include <type_traits>
template <class T, class U, class U2 /* assignable from U*/, class T2 = typename std::remove_reference<T>::type>
T&& set_parameter(T&& instance, U&& val, U2 (T2::* pmember))
{
(instance.*(pmember)) = std::forward<U>(val);
return std::forward<T>(instance);
}
这充满了细微差别。但足以说,它按照要求“有效”:
#include <iostream>
#include <string>
struct X
{
double foo;
std::string splurgle;
};
int main()
{
X x;
set_parameter(x, 3.14 , &X::foo);
set_parameter(x, "hello world", &X::splurgle);
std::cout << x.foo << ", " << x.splurgle;
}
输出:
3.14, hello world
增加精神错乱:请注意,通过返回有用的值,您可以做更多...有趣的事情,仍然:
return set_parameter(
set_parameter(X(), 3.14, &X::foo),
"hello world", &X::splurgle)
.splurgle.length();
答案 1 :(得分:0)
你可能可以使用指向成员的指针,但我不确定你是否会这样:
struct XX
{
char c;
int i;
};
template<class T, class U, class N>
void set_parameter(T &S, U val, N T::*n) {
for(auto &x: S) { x.*n = val; }
}
set_parameter(..., ..., &XX::c);
set_parameter(..., ..., &XX::i);