Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.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++ 是否可以将给定的一组运算符简化为任意的一组类?_C++_Templates_C++17_Operators_Factory Pattern - Fatal编程技术网

C++ 是否可以将给定的一组运算符简化为任意的一组类?

C++ 是否可以将给定的一组运算符简化为任意的一组类?,c++,templates,c++17,operators,factory-pattern,C++,Templates,C++17,Operators,Factory Pattern,考虑以下一组类及其运算符的关系:我们可以用两种不同的方式实现它们。第一个是在类内定义运算符,第二个是在类外定义运算符 template<typename T> struct A { T value; T& operator+(const A<T>& other) { return value + other.value; } // other operators }; temlate<typename T> str

考虑以下一组类及其运算符的关系:我们可以用两种不同的方式实现它们。第一个是在类内定义运算符,第二个是在类外定义运算符

template<typename T>
struct A {
    T value;

    T& operator+(const A<T>& other) { return value + other.value; }
    // other operators
}; 

temlate<typename T>
struct B {
   T value;
   
   T& operator+(const B<T>& other) { return value + other.value; }
};

// Or...
template<typename T>
struct A {
    T value;
};
template<typename T>
T& operator+(const A<T>& lhs, const A<T>& rhs) { return lhs.value + rhs.value; }
// ... other operators

template<typename T>
struct B {
    T value;
};
template<typename T>
T& operator+(const B<T>& lhs, const B<T>& rhs) { return lhs.value + rhs.value; }  
// ... other operators
模板
结构A{
T值;
T运算符+(常量A和其他){返回值+other.value;}
//其他操作员
}; 
特马特
结构B{
T值;
T运算符+(常量B和其他){返回值+other.value;}
};
//或者。。。
模板
结构A{
T值;
};
模板
T&operator+(常量A&lhs,常量A&rhs){返回lhs.value+rhs.value;}
// ... 其他操作员
模板
结构B{
T值;
};
模板
T&运算符+(常量B&lhs,常量B&rhs){返回lhs.value+rhs.value;}
// ... 其他操作员
<> P>有没有一种方法可以在C++中生成一个类或结构操作符,在这里我可以简单地声明或定义它们在任意的C类中,而不必为每个类写多个相同的操作符?我假设操作符对于定义它们的每个不同类都具有相同的行为和属性,因为它们都遵循相同的模式

例如:

template<typename T, class Obj>
struct my_operators {
    // define them here 
};

// Then
template<typename T>
struct A {
    T value;
    my_operators ops;
};

template<typename T>
struct B {
    T value;
    my_operators ops;
};
模板
结构my_运算符{
//在这里定义它们
};
//然后
模板
结构A{
T值;
my_operators;
};
模板
结构B{
T值;
my_operators;
};

请记住,我将此限制为C++17,因为我无法使用任何C++20功能,例如概念。。。如果这是可能的,我可以使用什么样的方法或构造,它的结构和正确的语法是什么样的?如果这是可能的,那么我就可以编写一次操作符,只要使用类的模式匹配就可以重用它们,而不必为每个单独的类编写这些操作符……

使用CRTP继承怎么样

#include <iostream>

template <typename T>
struct base_op
 {
   auto operator+ (T const & o) const
    { return static_cast<T&>(*this).value + o.value; }
 };

template<typename T>
struct A : public base_op<A<T>>
 { T value; }; 

template<typename T>
struct B : public base_op<B<T>>
 { T value; }; 

int main()
 {
   A<int>   a1, a2;
   B<long>  b1, b2;

   a1.value = 1;
   a2.value = 2;

   std::cout << a1+a2 << std::endl;

   b1.value = 3l;
   b2.value = 5l;

   std::cout << b1+b2 << std::endl;
 }
--编辑--

OP问道

现在,我正努力在相同的上下文中编写它们的等价的
+=
-=
*=
/=
运算符。。。有什么建议吗

这有点复杂,因为它们必须返回对派生对象的引用。。。我假设(例如)
operator+=()
,在
base\u op
中,可以是

T & operator+= (T const & o)
 {
   static_cast<T&>(*this).value += o.value;

   return static_cast<T&>(*this);
 }
T&operator+=(T常量和o)
{
静态_cast(*this).value+=o.value;
返回静态_cast(*此);
}

通过使用
CRTP
获取用户max66提供的答案,并在我的答案的评论部分借用用户SamVarshavchik提供的
透明比较器
的概念,我能够采用它们,并提出了这个实现设计:

template<class T>
struct single_member_ops {
    friend auto operator+(T const & lhs, T const & rhs) 
    { return lhs.value + rhs.value; }
    friend auto operator-(T const & lhs, T const & rhs) 
    { return lhs.value - rhs.value; }

    template<typename U>
    friend auto operator+(T const& lhs, const U& rhs) 
    { return lhs.value + rhs.value; }

    template<typename U>
    friend auto operator-(T const& lhs, const U& rhs )
    { return lhs.value - rhs.value;}    
};

template<typename T>
struct A : public single_member_ops<A<T>>{
    T value;    
    A() = default;
    explicit A(T in) : value{in} {}
    explicit A(A<T>& in) : value{in.value} {}
    auto& operator=(const T& rhs) { return value = rhs; }
};

template<typename T>
struct B : public single_member_ops<B<T>> {
    T value;
    B() = default;
    explicit B(T in) : value{in} {}
    explicit B(B<T>& in) : value{in.value} {}
    auto& operator=(const T& rhs) { return value = rhs; }
};

int main() {
    A<int> a1(4);
    A<int> a2;
    A<int> a3{0};
    a2 = 6;
    a3 = a1 + a2; 

    B<double> b1(3.4);
    B<double> b2(4.5);

    auto x = a1 + b2;
    auto y1 = a2 - b2;
    auto y2 = b2 - a1;

    return x;
}
模板
结构单成员操作{
friend auto operator+(T常量和左侧、T常量和右侧)
{返回lhs.value+rhs.value;}
friend自动操作员-(T常量和左侧、T常量和右侧)
{返回lhs.value-rhs.value;}
模板
friend auto operator+(T常量和左侧、常量U和右侧)
{返回lhs.value+rhs.value;}
模板
friend自动操作员-(T常量和左侧,常量U和右侧)
{返回lhs.value-rhs.value;}
};
模板
结构A:公共单成员操作


附加的
模板运算符
允许不同类型:
A
B
使用运算符,即使
T
U
对于
A
B
都不同,前提是
T
U
之间存在默认转换。但是,用户必须注意截断、溢出和下溢以及缩小转换,这取决于他们对
T
U

的选择。我可以想出一种方法,使用SFINAE为定义内部标记的任何类定义操作符重载,如typedef(类似于C++14及更高版本中,
是透明的
识别透明比较器的方式).然而,这感觉像是一个XY问题。你想解决什么问题?不,不是让操作符重载以这种方式工作的问题,而是解决方法涉及让操作符以这种方式工作的问题?@SamVarshavchik是的,这就是我一直在努力解决的问题…这会成为一个X/Y问题吗?…如果不是,那么如何?如果是,它会变成什么最好是代码重用!预处理器不参与模板参数推导。模板参数推导的规则非常精确,所以我不知道这里的歧义是什么意思。在任何情况下,您都可以看看透明比较器在C++14中是如何实现的,它们是如何工作的,并将其用作构建的指南您自己的重载。琐碎的挑剔:为
运算符+
返回
T&
似乎有点奇怪,因为它不是对立即超出范围的局部变量的引用吗?它似乎应该返回
T
。我想这可能适合我的需要。这将减少大量代码重复,因为不同的运算符类在其总体设计结构中都共享相同的属性集。我考虑了您关于使用CRTP的建议,并提出了以下实现,您可以在我提供的答案中找到,该答案仅作为参考点。让我知道您的想法……是否有任何改进,是否有任何遗漏或遗漏看,或者我应该开始一个新的Q/a,并要求那里指向这个Q/a?好的,我能够以这种方式实现基本的算术运算符,例如
+
-
*
,和
/
,但是,现在我正在努力编写它们的等价的
+=
-=
*=
/=/code>>同一上下文中的运算符…有什么建议吗?@FrancisCugler-关于您答案中的代码…我对运算符的模板版本有点困惑…没有
template<class T>
struct single_member_ops {
    friend auto operator+(T const & lhs, T const & rhs) 
    { return lhs.value + rhs.value; }
    friend auto operator-(T const & lhs, T const & rhs) 
    { return lhs.value - rhs.value; }

    template<typename U>
    friend auto operator+(T const& lhs, const U& rhs) 
    { return lhs.value + rhs.value; }

    template<typename U>
    friend auto operator-(T const& lhs, const U& rhs )
    { return lhs.value - rhs.value;}    
};

template<typename T>
struct A : public single_member_ops<A<T>>{
    T value;    
    A() = default;
    explicit A(T in) : value{in} {}
    explicit A(A<T>& in) : value{in.value} {}
    auto& operator=(const T& rhs) { return value = rhs; }
};

template<typename T>
struct B : public single_member_ops<B<T>> {
    T value;
    B() = default;
    explicit B(T in) : value{in} {}
    explicit B(B<T>& in) : value{in.value} {}
    auto& operator=(const T& rhs) { return value = rhs; }
};

int main() {
    A<int> a1(4);
    A<int> a2;
    A<int> a3{0};
    a2 = 6;
    a3 = a1 + a2; 

    B<double> b1(3.4);
    B<double> b2(4.5);

    auto x = a1 + b2;
    auto y1 = a2 - b2;
    auto y2 = b2 - a1;

    return x;
}