所以例如你有一个类似的类型:
public class EffectOptions
{
public EffectOptions ( params object [ ] options ) {}
public EffectOptions ( IEnumerable<object> options ) {}
public EffectOptions ( string name ) {}
public EffectOptions ( object owner ) {}
public EffectOptions ( int count ) {}
public EffectOptions ( Point point ) {}
}
Run Code Online (Sandbox Code Playgroud)
这里我只使用构造函数给出示例,但如果它们是类型本身的非构造方法,结果将是相同的,对吧?
所以当你这样做时:
EffectOptions options = new EffectOptions (null);
Run Code Online (Sandbox Code Playgroud)
会调用哪个构造函数,为什么?
我可以自己测试一下,但我想了解重载分辨率系统是如何工作的(不确定它是否被称为).
我正在尝试编写一个包含一些重载方法的C++类:
class Output
{
public:
static void Print(bool value)
{
std::cout << value ? "True" : "False";
}
static void Print(std::string value)
{
std::cout << value;
}
};
Run Code Online (Sandbox Code Playgroud)
现在让我说我调用方法如下:
Output::Print("Hello World");
Run Code Online (Sandbox Code Playgroud)
结果就是这样
真正
那么,为什么,当我定义该方法可以接受布尔值和字符串时,当我传入一个非布尔值时,它是否使用布尔重载?
编辑:我来自C#/ Java环境,对C++来说还是新手!
当我遇到这种特殊情况时,我正在实现同步/异步重载:
当我有一个没有参数或返回值的常规lambda表达式时,它会Run使用Action参数进行重载,这是可预测的.但是当lambda中有一个lambda时,while (true)它会通过Func参数进入重载状态.
public void Test()
{
Run(() => { var name = "bar"; });
Run(() => { while (true) ; });
}
void Run(Action action)
{
Console.WriteLine("action");
}
void Run(Func<Task> func) // Same behavior with Func<T> of any type.
{
Console.WriteLine("func");
}
Run Code Online (Sandbox Code Playgroud)
输出:
动作
功能
那怎么可能呢?有原因吗?
以下代码按预期失败,因为没有get找到重载.使用std::get会解决问题.
#include <array>
int main()
{
std::array<int, 2> ar{2,3};
auto r = get<0>(ar);//fails, get was not declared in this scope
}
Run Code Online (Sandbox Code Playgroud)
但是,引入模板化的版本get,即使它不匹配函数调用,也会使编译器使用以下std::get版本:
#include <array>
template <typename T>
void get(){};
int main()
{
std::array<int, 2> ar{2,3};
auto r = get<0>(ar);//returns 2
}
Run Code Online (Sandbox Code Playgroud)
我找不到解释这一点的标准的任何部分.这是我测试的所有3个编译器中的错误(可能不是),或者我错过了什么?
此行为已在测试中
编辑:我知道ADL.但是,如果ADL使第二个代码工作,为什么它不在第一部分?
下面的代码在Visual Studio 2013,gcc 4.8,clang 3.4和clang 3.5(Apple LLVM 6.0)中编译,但不在clang 3.6中编译(通过Apple LLVM 6.1)
代码是我们代码库中复杂类的简化版本,这是展示问题所需的最低要求.
问题的关键在于,复制结构TYPED_VALUE是在3.6中,STRING因为存在接受a的构造函数而对类型的模板化转换运算符进行求值STRING; 这导致std::is_constructible被评估导致它需要定义STRING(我们在这里不能提供 - 将导致完整代码中的循环依赖).
class STRING;
class TYPED_VALUE
{
public:
TYPED_VALUE( const TYPED_VALUE& ) = default; // explicit or implicit doesn't make a difference
TYPED_VALUE( const STRING & ) {}
template< typename TYPE, typename std::enable_if<!std::is_pointer< TYPE >::value && !std::is_constructible< TYPE, const STRING& >::value && !std::is_constructible< TYPE, bool >::value, int >::type = 0 >
operator TYPE( void ) const …Run Code Online (Sandbox Code Playgroud) clang conversion-operator language-lawyer overload-resolution c++11
我试图理解为什么std::function无法区分重载函数.
#include <functional>
void add(int,int){}
class A {};
void add (A, A){}
int main(){
std::function <void(int, int)> func = add;
}
Run Code Online (Sandbox Code Playgroud)
在上面显示的代码中,function<void(int, int)>只能匹配其中一个功能,但它会失败.为什么会这样?我知道我可以通过使用lambda或函数指针到实际函数然后将函数指针存储在函数中来解决这个问题.但为什么这会失败?关于我想要选择哪个功能的上下文不清楚吗?请帮助我理解为什么这会失败,因为我无法理解为什么在这种情况下模板匹配失败.
我得到的编译错误如下:
test.cpp:10:33: error: no viable conversion from '<overloaded function type>' to
'std::function<void (int, int)>'
std::function <void(int, int)> func = add;
^ ~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03:1266:31: note:
candidate constructor not viable: no overload of 'add' matching
'std::__1::nullptr_t' for 1st argument
_LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {}
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03:1267:5: note:
candidate constructor not viable: no overload of 'add' …Run Code Online (Sandbox Code Playgroud) #include <iostream>
struct uct
{
uct() { std::cerr << "default" << std::endl; }
uct(const uct &) { std::cerr << "copy" << std::endl; }
uct( uct&&) { std::cerr << "move" << std::endl; }
uct(const int &) { std::cerr << "int" << std::endl; }
uct( int &&) { std::cerr << "int" << std::endl; }
template <typename T>
uct(T &&) { std::cerr << "template" << std::endl; }
};
int main()
{
uct u1 ; // default
uct u2( 5); // int
uct u3(u1); …Run Code Online (Sandbox Code Playgroud) c++ copy-constructor constructor-overloading function-templates overload-resolution
我们最近从公司的VS2013搬到了VS2017.升级后,我们的代码库将不再构建.我们会收到以下错误:
以下方法或属性之间的调用不明确:'IRepository <T> .Get(object,params Expression <Func <T,object >> [])'和'IRepository <T> .Get(object,params string [] )"
这是呼叫本身:
this.mainRepository.Get(newEntity.Id);
Run Code Online (Sandbox Code Playgroud)
...和接口定义:
public interface IRepository<T> where T : class
{
T Get(object id, params Expression<Func<T, object>>[] includeExprs);
T Get(object id, params string[] includeExprs);
}
Run Code Online (Sandbox Code Playgroud)
我想知道这里是否有人可以解释为什么会这样.我怀疑C#6.0 的新改进方法重载解析功能,但查看语言规范我无法找出导致该问题的确切规则.
编辑
我写了一篇关于这个问题的后续博客文章:http://codewithstyle.info/method-overload-resolution-in-c-6-0-an-interesting-bug-story
#include <iostream>
template<typename T>
struct identity
{
typedef T type;
};
template<typename T> void bar(T) { std::cout << "a" << std::endl; }
template<typename T> void bar(typename identity<T>::type) { std::cout << "b" << std::endl; }
int main ()
{
bar(5); // prints "a" because of template deduction rules
bar<int>(5); // prints "b" because of ...?
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
我预计bar<int>(5)至少会产生歧义.这里涉及到关于模板函数重载决策的疯狂规则?
我试图理解为什么编译器无法解析bar方法调用。我希望bar(Xyz::new)始终选择bar(Supplier)因为bar(T extends Xyz)由于 的上限而永远无法匹配Xyz。
public <T extends Xyz> void foo(T s) {}
public <T extends Xyz> void bar(T s) {}
public <T extends Xyz> void bar(Supplier<T> s) {}
public void example() {
foo(Xyz::new); // not valid (does not extend Xyz)
bar((Supplier<Xyz>) Xyz::new); // valid (explicitly a Supplier)
bar(Xyz::new); // ambiguous - but only one method is valid?
}
public static class Xyz {}
Run Code Online (Sandbox Code Playgroud)
如果bar(T)不适用,即使单独使用(如 所示foo(T)),那么唯一的选择肯定是bar(Supplier) …