我想在 C++ 中使用“按签名隐藏”而不是“按名称隐藏”。所以我写了一个宏,它定义了一个可变参数函数,如果存在的话,它将所有调用委托给它的基类。我不能使用 using 声明,因为如果基类没有具有该名称的方法,我不希望它失败 - 并且只有在没有直接成员匹配时才应考虑继承的方法。这在大多数情况下都有效,因为它是由可变参数函数实现的,与非可变参数函数相比,它总是更差的候选者。但是当子类也具有可变参数函数时,我遇到了问题->调用变得模棱两可。
所以我得到以下情况(简化 - 没有sfinae,宏......):
#include <type_traits>
#include <iostream>
class A{
public:
void Do(){
std::cout << "A::Do()\n";
}
};
class B : public A
{
public:
template<
typename... TX,
typename SomeSFINAE = int
>
void Do(TX...){
std::cout << "B::Do()\n";
}
template<typename... T>
void Do(T...){
A::Do();
}
};
int main(){
B b;
b.Do();
return 0;
}
在godbolt上看到它。
我想在不将其中一种方法设为“调度程序方法”的情况下解决这种情况。有没有办法让一种方法成为解决这种歧义的“更糟糕的候选者”?
更新
似乎不清楚我真正想要实现的目标。所以这里有一些带有注释的“伪代码”:
#include <type_traits>
#include <iostream>
class A{
public:
void Do(){
std::cout << "A::Do()\n";
}
};
class B : public A
{
public:
template<
typename... TX
>
void Do(TX...){
std::cout << "B::Do()\n";
}
using A::Do; //<--- This should be considered only if no direct match is found in B
//Variadic function should win, because it is defined in B not in A - it should hide A.Do
//It should even work if A has NO method Do
};
int main(){
B b{};
b.Do(); //-> B::Do should be called, not A::Do
return 0;
}
更新
我想从你这里得到类似的东西,如何让普通函数成为变差函数的更差候选者。
例如:
#include <iostream>
void Do(int a){
std::cout << "better";
}
template<typename... T>
void Do(int a, T...){
//this is worse
std::cout << "worse";
}
int main(){
Do(42);
return 0;
}
有什么东西可以使可变参数功能变得更糟吗?
背景:目前我有以下宏,只是为了模拟我想要的使用。
#define NATIVE_DO_NOT_HIDE_INHERITED_(AMETHOD, ...) \
private: template<typename $T, typename... $Args> \
using CallHiding$ ## AMETHOD = decltype(::std::declval<$T*>()->AMETHOD (::std::declval<$Args>()...)); \
\
public: template< \
typename... $Args \
, typename $Dependent = __VA_ARGS__ \
, bool $Detected = ::CORE_NATIVE_NS ::is_detected_v<CallHiding$ ## AMETHOD, $Dependent, $Args...> \
, typename = typename ::std::enable_if_t<$Detected > \
> \
constexpr decltype(auto) AMETHOD ($Args&&... args) \
{ \
/*allow virtual call*/ \
return static_cast<$Dependent*>(this) -> AMETHOD (::std::forward<$Args>(args)...); \
} \
\
private: template<typename $T, typename $FktArgsTuple, typename $ValueArgsTuple> \
class CallHidingGeneric$ ## AMETHOD : public ::std::bool_constant<false> {\
};\
\
private: template<typename $T, typename... $FktArgs, typename... $ValueArgs> \
class CallHidingGeneric$ ## AMETHOD<$T, ::std::tuple<$FktArgs...>, ::std::tuple<$ValueArgs...>> \
{\
template<typename AType> \
using ATemplate = decltype(::std::declval<AType>().template AMETHOD <$FktArgs...> (::std::declval<$ValueArgs>()...)); \
public: \
constexpr static bool value = ::CORE_NATIVE_NS ::is_detected_v<ATemplate, $T> ; \
}; \
\
public: template< \
typename... $FktArgs \
, typename... $Args \
, typename $Dependent = __VA_ARGS__ \
, typename = ::std::enable_if_t<(sizeof...($FktArgs) > 0)> \
, typename = ::std::enable_if_t< \
CallHidingGeneric$ ## AMETHOD<$Dependent, typename ::std::template tuple<$FktArgs...>, typename ::std::template tuple<$Args...>>::value \
> \
> \
constexpr decltype(auto) AMETHOD ($Args&&... args) \
{ \
return $Dependent ::template AMETHOD <$FktArgs...> (::std::forward<$Args>(args)...); \
}
#define NATIVE_DO_NOT_HIDE_INHERITED(AMETHOD) NATIVE_DO_NOT_HIDE_INHERITED_(AMETHOD, $Next)
#define NATIVE_DO_NOT_HIDE_INHERITED2(AMETHOD, ...) NATIVE_DO_NOT_HIDE_INHERITED_(AMETHOD, typename ::CORE_NATIVE_NS::type_container_t< __VA_ARGS__ >:: $Next)
它适用于“正常”功能 - 但“宏生成功能”并不被认为更糟......