Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 模板类似python的setattr函数_C++_Templates_C++11_Stl - Fatal编程技术网

C++ 模板类似python的setattr函数

C++ 模板类似python的setattr函数,c++,templates,c++11,stl,C++,Templates,C++11,Stl,通过阅读之前的答案,我觉得我可能有一个设计问题,但即使答案是学术性的,我仍然想知道这是否可能。我用Python编程已经有一段时间了,它证明了这一点。我试图创建一个类似于访问对象的东西。手工操作看起来像: template<class T, class U> void set_parameter_sigma(T &S, U val) { for(auto &x: S) { x.sigma = val; } } template<class T, class

通过阅读之前的答案,我觉得我可能有一个设计问题,但即使答案是学术性的,我仍然想知道这是否可能。我用Python编程已经有一段时间了,它证明了这一点。我试图创建一个类似于访问对象的东西。手工操作看起来像:

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; }
}
模板
无效集\参数\西格玛(T&S,U val){
对于(auto&x:S){x.sigma=val;}
}
样板
无效集\参数\ε(T&S,U val){
对于(auto&x:S){x.epsilon=val;}
}
样板
无效集参数长度(T&S,U值){
对于(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; }
}
模板
无效集参数(T&S,U值){
对于(auto&x:S){x.N=val;}
}

我可以像
set\u parameter(foo,2.0,“epsilon”)
那样调用它,编译器将自动创建
set\u parameter\u epsilon
函数。虽然我相信boost可以做到这一点,但如果可能的话,我更希望看到仅使用STL的版本。

您可能可以使用指向成员的指针来实现这一点,但我不确定您是否会喜欢:

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);
struct XX
{
字符c;
int i;
};
样板
void set_参数(T&S,U val,N T::*N){
对于(auto&x:S){x.*n=val;}
}
设置_参数(…,…,&XX::c);
设置_参数(…,…,&XX::i);

您可能可以为此使用指向成员的指针,但我不确定您是否会喜欢:

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);
struct XX
{
字符c;
int i;
};
样板
void set_参数(T&S,U val,N T::*N){
对于(auto&x:S){x.*n=val;}
}
设置_参数(…,…,&XX::c);
设置_参数(…,…,&XX::i);
更新: Oops结果是我错过了在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";
}

原始答复文本:
对于额外的疯狂:请注意,通过返回一个有用的值,您可以做更多。。。有趣的事情,仍然是:

return set_parameter(
        set_parameter(X(), 3.14, &X::foo),
        "hello world", &X::splurgle)
    .splurgle.length();
更新: Oops结果是我错过了在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";
}

原始答复文本:
对于额外的疯狂:请注意,通过返回一个有用的值,您可以做更多。。。有趣的事情,仍然是:

return set_parameter(
        set_parameter(X(), 3.14, &X::foo),
        "hello world", &X::splurgle)
    .splurgle.length();

这不会推断出
t
。另外,如果您使用任何隐式转换赋值,它也不会推断
N
,也不会推断
t
。此外,如果您使用任何隐式转换赋值,它也不会推断出
N
。请仔细查看!虽然我不完全理解模板定义中的所有内容,特别是关于
删除引用
转发
@Hooked转发的部分,但是@Hooked转发使得设置参数((X())、3.14、&X::foo)
和享受指定值的移动语义成为可能。
remove\u引用
有助于推断,因为对于
左值
T
将被推断为
X&
,但是
T2
需要不合格。@MooingDuck我想我改变了不确定的一点:/Added a。。。用例来演示它何时“有用”(在本例中是为了以更模糊的方式从
main
返回11;
)@Hooked我错过了关于迭代容器的部分。修正了。再一次,看它整洁!虽然我不完全理解模板定义中的所有内容,特别是关于
删除引用
转发
@Hooked转发的部分,但是@Hooked转发使得设置参数((X())、3.14、&X::foo)
和享受指定值的移动语义成为可能。
remove\u引用
有助于推断,因为对于
左值
T
将被推断为
X&
,但是
T2
需要不合格。@MooingDuck我想我改变了不确定的一点:/Added a。。。用例来演示它何时“有用”(在本例中是为了以更模糊的方式从
main
返回11;
)@Hooked我错过了关于迭代容器的部分。修正了。再一次,我想不出任何理由使用setattr?为什么不为(auto&x:foo)x.epsilon=2.0?不要试图让一种语言表现得像另一种语言。这样做是徒劳的。相关:我想不出任何理由使用setattr?为什么不为(auto&x:foo)x.epsilon=2.0?不要试图让一种语言表现得像另一种语言。这样做是徒劳的
return set_parameter(
        set_parameter(X(), 3.14, &X::foo),
        "hello world", &X::splurgle)
    .splurgle.length();