我如何检查特定的模板参数是相同的

发布于 2025-02-03 02:32:47 字数 2099 浏览 2 评论 0原文

我有一个带有三个模板参数的类:

template<typename A, typename B, typename C>
class Unit;

然后,我有一个代表此类及其专业化的概念:

template <typename T>
struct is_unit : std::false_type {};

template<typename A, typename B, typename C>
struct is_unit<Unit<A, B, C>> : std::true_type {};

template <typename T>
constexpr bool is_unit_v = is_unit<T>::value;

template <typename T>
concept Unit_T = is_unit_v<T>;

在单位类的定义中,我想要一个函数,该函数返回一个具有不同专业化的单元,该功能与该功能所为的函数不同称为。我希望用户提供所需的返回类型。到目前为止,我的工作正常:

template<typename A, typename B, typename C>
class Unit {
public:
    // Other member stuff...

    template<Unit_T U>
    U as() { return U(*this); }
}

Unit<MyType, long double, MyOtherType> unit;
// Do stuff to unit.
auto unit2 = unit.as<Unit<MyType, long int, AnotherType>();

所有这些都按预期工作。但是,还有一个要求,我无法弄清楚如何实施。所需类型的第一个模板参数必须匹配所调用类型的第一个模板参数。因此:

Unit<MyType, long double, MyOtherType> unit;
// Do stuff to unit.
auto unit2 = unit.as<Unit<YetAnotherType, long int, AnotherType>();

不应该编译。

我认为正确的方法看起来像:

template<typename A, typename B, typename C>
class Unit {
public:
    // Other member stuff...

    template<Unit_T U>
    requires std::is_same_v<U<D>, D>
    // or maybe std::is_same_V<U::D, D> ?
    U as() { return U(*this); }
}

但这是行不通的。而且,据我了解,即使这是正确的模板参数为正确类型的正确方法,我也无法进一步限制概念。

我尝试为具有特定第一个模板参数的单元编写另一个概念:

template<typename U, typename D>
concept UnitFirstType = is_unit_v<U> && std::is_same_v<U<D> /* or U::D */, D>;

但这是行不通的。

问题似乎在于我如何使用std :: is_same_v。我只是不知道如何使用模板参数使用它。

因此,实现这一目标的正确方法是什么:

Unit<MyType, long double, MyOtherType> unit;
auto unit2 = unit.as<Unit<MyType, long int, AnotherType>(); // will compile
// auto unit3 = unit.as<Unit<YetAnotherType, long int, AnotherType>(); // should not compile

I have a class with three template parameters:

template<typename A, typename B, typename C>
class Unit;

Then I have a concept representing this class and all its specialization:

template <typename T>
struct is_unit : std::false_type {};

template<typename A, typename B, typename C>
struct is_unit<Unit<A, B, C>> : std::true_type {};

template <typename T>
constexpr bool is_unit_v = is_unit<T>::value;

template <typename T>
concept Unit_T = is_unit_v<T>;

In the definition of the Unit class, I want a function that returns a Unit with a different specialization from the one through which the function is called. I want the user to provide the desired return type. I have this working so far:

template<typename A, typename B, typename C>
class Unit {
public:
    // Other member stuff...

    template<Unit_T U>
    U as() { return U(*this); }
}

Unit<MyType, long double, MyOtherType> unit;
// Do stuff to unit.
auto unit2 = unit.as<Unit<MyType, long int, AnotherType>();

That all works as expected. There's one more requirement, however, that I can't figure out how to implement. The first template parameter of the desired type must match the first template parameter of the type through which it was called. So this:

Unit<MyType, long double, MyOtherType> unit;
// Do stuff to unit.
auto unit2 = unit.as<Unit<YetAnotherType, long int, AnotherType>();

should not compile.

I would think that the correct way to do this would look something like:

template<typename A, typename B, typename C>
class Unit {
public:
    // Other member stuff...

    template<Unit_T U>
    requires std::is_same_v<U<D>, D>
    // or maybe std::is_same_V<U::D, D> ?
    U as() { return U(*this); }
}

But that doesn't work. And, as I understand, even if that was the right way to require a template parameter be the right type, I can't further constrain a concept.

I tried writing another concept for a Unit with a specific first template parameter:

template<typename U, typename D>
concept UnitFirstType = is_unit_v<U> && std::is_same_v<U<D> /* or U::D */, D>;

But that doesn't work.

The problem seems to lie in how I'm using std::is_same_v. I just don't know how to use it with a template parameter.

So what is the proper way to achieve this:

Unit<MyType, long double, MyOtherType> unit;
auto unit2 = unit.as<Unit<MyType, long int, AnotherType>(); // will compile
// auto unit3 = unit.as<Unit<YetAnotherType, long int, AnotherType>(); // should not compile

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

会傲 2025-02-10 02:32:47

这可能是您想要的

template<typename A, typename B, typename C>
class Unit;

template<typename U, typename A>
constexpr bool unit_first_type = false;

template<typename A, typename B, typename C>
constexpr bool unit_first_type<Unit<A, B, C>, A> = true;

template<typename U, typename A>
concept UnitFirstType = unit_first_type<U, A>;

template<typename A, typename B, typename C>
class Unit {
 public:
  // Other member stuff...
  template<UnitFirstType<A> U>
  U as();
};

demo

This is probably what you want

template<typename A, typename B, typename C>
class Unit;

template<typename U, typename A>
constexpr bool unit_first_type = false;

template<typename A, typename B, typename C>
constexpr bool unit_first_type<Unit<A, B, C>, A> = true;

template<typename U, typename A>
concept UnitFirstType = unit_first_type<U, A>;

template<typename A, typename B, typename C>
class Unit {
 public:
  // Other member stuff...
  template<UnitFirstType<A> U>
  U as();
};

Demo

白鸥掠海 2025-02-10 02:32:47

我想您可以使用良好的老年人(C ++ 20)sfinae。

例如,给定一个自定义类型特征如下所示,

template <typename, typename>
struct firstEqual : public std::false_type
{};

template <typename A, typename B1, typename C1, typename B2, typename C2>
struct firstEqual<Unit<A, B1, C1> const, Unit<A, B2, C2> const>
   : public std::true_type
{};

/disable 为()

template <typename U>
std::enable_if_t<firstEqual<Unit<A, B, C> const, U const>::value, U>
   as() { return U{}; }

您可以启用 具有不同的constness,但相同的第一个模板参数...以防万一您想要什么。

还观察到您不再需要unit_t概念。

以下是一个完整的汇编示例

#include <type_traits>

template<typename A, typename B, typename C>
class Unit;

template <typename, typename>
struct firstEqual : public std::false_type
{};

template <typename A, typename B1, typename C1, typename B2, typename C2>
struct firstEqual<Unit<A, B1, C1> const, Unit<A, B2, C2> const>
   : public std::true_type
{};

template <typename A, typename B, typename C>
class Unit {
  public:
    // Other member stuff...

    template <typename U>
    std::enable_if_t<firstEqual<Unit<A, B, C> const, U const>::value, U>
       as() { return U{}; }
};



int main()
{
  Unit<int, long double, void> unit;

  auto unit2 = unit.as<Unit<int, long, float>>();  // compile
  //auto unit3 = unit.as<Unit<char, long, float>>(); // compilation error
}

I suppose you can use the good-old (pre C++20) SFINAE.

For example, given a custom type traits as follows

template <typename, typename>
struct firstEqual : public std::false_type
{};

template <typename A, typename B1, typename C1, typename B2, typename C2>
struct firstEqual<Unit<A, B1, C1> const, Unit<A, B2, C2> const>
   : public std::true_type
{};

you can enable/disable as() as follows

template <typename U>
std::enable_if_t<firstEqual<Unit<A, B, C> const, U const>::value, U>
   as() { return U{}; }

Observe the use of const, to accept the case of different Units with different constness but the same first template argument... just in case is what do you want.

Observe also that you don't need the Unit_T concept any more.

The following is a full compiling example

#include <type_traits>

template<typename A, typename B, typename C>
class Unit;

template <typename, typename>
struct firstEqual : public std::false_type
{};

template <typename A, typename B1, typename C1, typename B2, typename C2>
struct firstEqual<Unit<A, B1, C1> const, Unit<A, B2, C2> const>
   : public std::true_type
{};

template <typename A, typename B, typename C>
class Unit {
  public:
    // Other member stuff...

    template <typename U>
    std::enable_if_t<firstEqual<Unit<A, B, C> const, U const>::value, U>
       as() { return U{}; }
};



int main()
{
  Unit<int, long double, void> unit;

  auto unit2 = unit.as<Unit<int, long, float>>();  // compile
  //auto unit3 = unit.as<Unit<char, long, float>>(); // compilation error
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文