模板函数上指定类型的常量/非常量引用的参数匹配的 C++ 概念

问题描述 投票:0回答:1

我想知道是否有更好的方法来解决这样的模板函数的代码重复问题

struct Z {
    void doSomething() { std::cout << "non-const version\n"; }
    void doSomething() const { std::cout << "const version\n"; }
};

void tempFunc( Z& z ) {
    z.doSomething(); // calls non-const member function
}
void tempFunc( const Z& z ) {
    z.doSomething(); // calls const member function
}

int main() {
    Z z;
    const Z cz;
    tempFunc(z);
    tempFunc(cz);
    return 0;
}

如您所见, tempFunc 的两个定义是相同的,因此为了避免代码重复,我使用这样的约束在 C++20 下重写了该函数

void tempFunc( std::convertible_to<Z> auto&& z ) {
    z.doSomething();
}

注意 std::is_convertible_to<> 的使用,它工作得很好,但我怀疑应该有一个标准(或者如果不是一个容易编写的约束)来使用 is_convertible_to<> 来限制参数仅匹配 const和非常量引用。

c++ constraints c++20 argument-matching
1个回答
1
投票

std::convertible_to
是错误的概念。您不想要可转换为
Z
的东西。您需要
Z
的东西。

或者,不是特别是 is-a,因为

Z const
Z&&
都不是字面上的
Z
,但你也想允许它们。

为此,人们通常会写的是:

template <typename T, typename U>
concept DecaysTo = std::same_as<std::decay_t<U>, T>;

用作:

void tempFunc( DecaysTo<Z> auto&& z ) {
    z.doSomething();
}

现在匹配任何类型

T
,使得
std::decay_t<T>
Z
。基本上就是
Z [const][&|&&]
。这就是你想要的。

© www.soinside.com 2019 - 2024. All rights reserved.