绑定enable_if成员函数



在enable_if'd成员函数上调用bind时会出错。我已经使用if constexpr解决了这个问题,但我很好奇这个问题的解决方案是什么。代码是最简单的再现器,并不代表我试图解决的首要问题。我该怎么做呢?

#include <iostream>
#include <type_traits>                                                                                                                                                                                                                                            
#include <functional>                                                                                                                                                                                                                                       
template <typename T>                                                                                                                                                                                                                                           
class test {                                                                                                                                                                                                                                                    
public:                                                                                                                                                                                                                                                         
template <typename U = T>                                                                                                                                                                                                                                     
typename std::enable_if<std::is_copy_constructible<U>::value, void>::type                                                                                                                                                                                     
foo(const T& v){
std::cout << "copy constructible";
}                                                                                                                                                                                                                                              
template <typename U = T>                                                                                                                                                                                                                                     
typename std::enable_if<!std::is_copy_constructible<U>::value, void>::type                                                                                                                                                                                     
foo(const T& v){
std::cout << "not copy constructible";
}                                                                                                                                                           
void foo_bar(const T& v){
std::cout << "test";
}
};                                                                                                                                                                                                                                                              

int main(int argn, char** argc){                                                                                                                                                                                                                                
                                                                                                                                                                       
test<int> myfoo;           
myfoo.foo(3); //Works           
auto func = std::bind(&test<int>::foo_bar, &myfoo, 3);  //Works                                                                                                                                                                                                                      
auto func = std::bind(&test<int>::foo, &myfoo, 3); //Doesn't work                                                                                                                                                                                             
func();                                                                                                                                                                                                                                                       
return 0;                                                                                                                                                                                                                                                     
}                                                                                                                                                                                                                                                               

问题是U只在实际调用成员函数模板foo时被替换,而不是在std::bind()内部使用时。这意味着当在bind()中指定&test<int>::foo时,不知道两个成员函数模板中的哪一个将实际实例化,因为定义的实例化将在我们实际调用foo()时发生,因此编译器无法确定您引用的是哪一个。这正是<unresolved overloaded function type>在你得到的错误中的意思:

no matching function for call to 'bind(<unresolved overloaded function type>, test<int>*, int)'
32 |   auto func2 = std::bind(&test<int>::foo, &myfoo, 3); //Doesn't work
|                ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~

您可以通过显式指定U来解决这个问题,如:

&test<int>::foo<int>

或使用lambda,如:

auto func = [&myfoo]() { myfoo.foo(3); };


在c++ 20中有第三种方法可以使用requires-clause解决这个问题,如下所示。注意,下面的程序是格式良好的,但是gcc和msvc错误地拒绝了它。只有clang接受它,这是正确的行为。演示

#include <iostream>
#include <type_traits>                                                                                                                                                                                                                                            
#include <functional>                                                                                                                                                                                                                                       
template <typename T>                                                                                                                                                                                                                                           
class test {                                                                                                                                                                                                                                                    
public:                                                                                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                                                   
void foo(const T& v) requires std::is_copy_constructible_v<T>{
std::cout << "copy constructible";
}                                                                                                                                                                                                                                              
void foo(const T& v) requires (!std::is_copy_constructible_v<T>) {
std::cout << "non copy constructible";
} 
                                                                                     
void foo_bar(const T& v){
std::cout << "test";
}
};                                                                                                                                                                                                                                                              
int main(int argn, char** argc){                                                                                                                                                                                                                                
                                                                                                                                                                       
test<int> myfoo;           
myfoo.foo(3); //Works           
auto func = std::bind(&test<int>::foo_bar, &myfoo, 3);  //Works                                                                                                                                                                                                                      
auto func2 = std::bind(&test<int>::foo, &myfoo, 3); //works                                                                                                                                                                                           
func(); 
func2();                                                                                                                                                                                                                                                      
}  

相关内容

  • 没有找到相关文章

最新更新