lig*_*ulb 6 c++ templates crtp ambiguous c++17
我有几个我想为CRTP基类的派生类工作的函数。问题是,如果我将派生类传递给用于CRTP类的自由函数,则会产生歧义。下面的代码是一个说明这个问题的最小示例:
template<typename T>
struct A{};
struct C : public A<C>{};
struct B{};
template<typename T, typename U>
void fn(const A<T>& a, const A<U>& b)
{
std::cout << "LT, RT\n";
}
template<typename T, typename U>
void fn(const T a, const A<U>& b)
{
std::cout << "L, RT\n";
}
template<typename T, typename U>
void fn(const A<T>& a, const U& b)
{
std::cout << "LT, R\n";
}
int main()
{
C a; // if we change C to A<C> everything works fine
B b;
fn(a,a); // fails to compile due to ambiguous call
fn(b,a);
fn(a,b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,我希望此方法适用于派生类,就像我要使用基类一样(不必为基类重新定义所有内容,CRTP习惯用法的全部要点是不必为多个类定义fn )。
首先,您需要一个特征以查看某些事物是否类似A。您不能只is_base_of在这里使用,因为您不知道将从哪个 A继承。我们需要使用额外的间接方式:
template <typename T>
auto is_A_impl(A<T> const&) -> std::true_type;
auto is_A_impl(...) -> std::false_type;
template <typename T>
using is_A = decltype(is_A_impl(std::declval<T>()));
Run Code Online (Sandbox Code Playgroud)
现在,我们可以使用此特征来编写我们的三个重载:both A,only left A和only right A:
#define REQUIRES(...) std::enable_if_t<(__VA_ARGS__), int> = 0
// both A
template <typename T, typename U, REQUIRES(is_A<T>() && is_A<U>())
void fn(T const&, U const&);
// left A
template <typename T, typename U, REQUIRES(is_A<T>() && !is_A<U>())
void fn(T const&, U const&);
// right A
template <typename T, typename U, REQUIRES(!is_A<T>() && is_A<U>())
void fn(T const&, U const&);
Run Code Online (Sandbox Code Playgroud)
请注意,我只是在接受T,U这里,我们不一定要丢脸并丢失信息。
关于C ++ 20中即将出现的概念的一件好事是编写此代码要容易得多。这两个特征现在变成了一个概念:
template <typename T> void is_A_impl(A<T> const&);
template <typename T>
concept ALike = requires(T const& t) { is_A_impl(t); }
Run Code Online (Sandbox Code Playgroud)
以及三个重载:
// both A
template <ALike T, ALike U>
void fn(T const&, U const&);
// left A
template <ALike T, typename U>
void fn(T const&, U const&);
// right A
template <typename T, ALike U>
void fn(T const&, U const&);
Run Code Online (Sandbox Code Playgroud)
语言规则已经强制在可行的情况下,首选“ A重载”。好东西。
| 归档时间: |
|
| 查看次数: |
104 次 |
| 最近记录: |