如何在C++中将一个类定义重用为不同的类

huangapple go评论65阅读模式
英文:

In C++ how to reuse a class definition as a different class

问题

假设我们有一个类定义

class Foo {...};

我知道我们可以使用usingtypedef来重用它的定义

using Bar = Foo; // 或者 typedef Foo Bar;

但它们被视为相同的类型,也就是说编译器将以下内容视为重定义

void fun(const Foo&) { cout<<"It is Foo"<<endl; }
void fun(const Bar&) { cout<<"It is Bar"<<endl; }

是否有可能或有解决方法,可以重用定义,使编译器将它们视为不同的类型?


感谢您的解决方案和讨论
以下是我的情况的一些细节:
类会声明它们的相关类型,而这些类型可以是相同的。

struct MyFoo { using type = SomeRelated; };
struct MyBar { using type = SomeRelated; };

另一个类将使用上述类的相关类型进行构造,我希望构造函数能够区分它们

struct MyClass
{
    MyClass(const MyFoo::type&) {cout<<"ctor from MyFoo"<<endl;}
    MyClass(const MyBar::type&) {cout<<"ctor from MyBar"<<endl;}
};
英文:

Say we have a class definition

class Foo {...};

I know we can reuse its definition with using or typedef

using Bar = Foo; // or typedef Foo Bar;

But they are treat as a same type, that is to say the compiler treat following as redefinition

void fun(const Foo&amp;) { cout&lt;&lt;&quot;It is Foo&quot;&lt;&lt;endl; }
void fun(const Bar&amp;) { cout&lt;&lt;&quot;It is Bar&quot;&lt;&lt;endl; }

Is there any possible or work around we can reuse definition that compiler treat as different types


Thanks for your solution and discussion
Here are some details of my case:
classes would declare their related type. and the type could be the same.

struct MyFoo { using type = SomeRelated; };
struct MyBar { using type = SomeRelated; };

Another class would be contructed with the related type of above classes and I want the constructor can distinguish from them

struct MyClass
{
    MyClass(const MyFoo::type&amp;) {cout&lt;&lt;&quot;ctor from MyFoo&quot;&lt;&lt;endl;}
    MyClass(const MyBar::type&amp;) {cout&lt;&lt;&quot;ctor from MyBar&quot;&lt;&lt;endl;}
};

</details>


# 答案1
**得分**: 4

你可以通过使用类模板来实现,模板实例始终是不同的类型。
```cpp
template <int>
class Impl {
  // 在这里实现你的 Foo
};

using Foo = Impl<1>;
using Bar = Impl<2>;

或者使用继承(你不需要记住上面使用的最后一个数字)。

template <typename>
class Impl {
  // 在这里实现你的 Foo
};

class Foo : public Impl<Foo> {};
class Bar : public Impl<Bar> {};
英文:

You can make it with help of a class template, template instances are always different types.

template &lt;int&gt;
class Impl {
  // Implement like your Foo here
};

using Foo = Impl&lt;1&gt;;
using Bar = Impl&lt;2&gt;;

Or with the inherence (you don't need to recall the last used number above).

template &lt;typename&gt;
class Impl {
  // Implement like your Foo here
};

class Foo : public Impl&lt;Foo&gt; {};
class Bar : public Impl&lt;Bar&gt; {};

答案2

得分: 1

这被称为强制类型定义模式/问题。存在许多部分解决方案,但大多数都考虑了基本的C++类型。对于类类型,使用继承更容易:

class foo;
class bar : public foo
{ using foo::foo; }; // 启用所有foo构造函数

对于其他类型,可以使用CRTP和装箱值的组合:

#include <type_traits>
template<typename this_type, typename value_type>
    requires(std::is_final_v<value_type> || 
         not std::is_class_v<value_type>)
struct strong_alias
{ value_type value; };

struct my_int: strong_alias<my_int,int>{};

my_int i{3};
i.value += 4;

还有其他方法可供选择,但它们通常会导致复杂且难以阅读的代码。

英文:

This is known as the strong typedef idiom/problem. There exist many partial solutions, but mostly fundamental C++ types are considered. For class types, it is easier to use inheritance:

class foo;
class bar : public foo
{ using foo::foo; }; //enable all foo constructors

For other types a combination of CRTP and boxed value can be used:

#include &lt;type_traits&gt;
template&lt;typename this_type, typename value_type&gt;
    requires(std::is_final_v&lt;value_type&gt; || 
         not std::is_class_v&lt;value_type&gt;)
struct strong_alias
{ value_type value; };

struct my_int: strong_alias&lt;my_int,int&gt;{};

my_int i{3};
i.value += 4;

Other approaches are available too, but they generally lead to complex and hard to read code.

答案3

得分: 0

你无法通过简单地使用重新定义类型来使它们不同。

但是,如果你试图将相同类型传递给同名但具有不同实现的函数,请调整函数参数签名。试用以下代码:

#include <iostream>

class foo {
};

void test(const foo&)      { std::cout << "void test(const foo&)\n"; }
void test(const foo&, int) { std::cout << "void test(const foo&, int)\n"; }

int main() {
    foo f;
    test(f);
    test(f, 0);
    return 0;
}
英文:

You cannot make them different by simply using re-define-type.

But if you are trying to pass same type to functions having same name but different implementation, give a tuning to function parameter signature. Try the code below.

#include &lt;iostream&gt;

class foo {
};

void test(const foo&amp;)      { std::cout &lt;&lt; &quot;void test(const foo&amp;)\n&quot;; }
void test(const foo&amp;, int) { std::cout &lt;&lt; &quot;void test(const foo&amp;, int)\n&quot;; }

int main() {
	foo f;
	test(f);
	test(f, 0);
    return 0;
}

huangapple
  • 本文由 发表于 2023年5月30日 09:36:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76361115.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定