我看到了以下代码:
class NullClass {
public:
template<class T> operator T*() const { return 0; }
};
const NullClass NULL;
void f(int x);
void f(string *p);
f(NULL); // converts NULL to string*, then calls f(string*)
Run Code Online (Sandbox Code Playgroud)
Q1>我有理由理解以下声明
template<class T> operator T*() const { return 0; }
Run Code Online (Sandbox Code Playgroud)
特别是,是什么意思operator T*()?
Q2>为什么f(NULL)最终触发f(string*)?
谢谢
在具有各种Func委托重载的函数中使用匿名方法时,我在Visual Studio 2010中遇到了一些奇怪的行为.
我在下面创建了一个小型复制课程.
考虑这个ListViewAdapter类
namespace LambdaTestApp
{
public class ListViewAdapter<T>
{
private Func<int, string, int, string> _converter1;
private Func<RefType1, string, string> _converter2;
public ListViewAdapter(int arg1, Func<int, string, int, string> converter)
{
_converter1 = converter;
}
public ListViewAdapter(int arg1, Func<RefType1, string, string> converter)
{
_converter2 = converter;
}
public static ListViewAdapter<T> MockPopulate(int arg, Func<int, string, int, string> converter) {
ListViewAdapter<T> instance = new ListViewAdapter<T>(arg, converter);
return instance;
}
public static ListViewAdapter<T> MockPopulate(int arg, Func<RefType1, string, string> converter)
{
ListViewAdapter<T> instance …Run Code Online (Sandbox Code Playgroud) 我正在编写一个序列化程序,我希望广泛使用方法重载,序列化派生类型的对象IEnumerable<T>,IDictionary<K,V>等等.
我还打算使用dynamic关键字让CLR根据要序列化的对象的运行时类型选择正确的重载.
看看这段代码:
void Serialize<TKey, TValue>(IDictionary<TKey, TValue> dictionary)
{
Console.WriteLine("IDictionary<TKey, TValue>");
}
void Serialize<TKey, TValue>(IEnumerable<KeyValuePair<TKey, TValue>> items)
{
Console.WriteLine("IEnumerable<KeyValuePair<TKey, TValue>>");
}
void Serialize<T>(IEnumerable<T> items)
{
Console.WriteLine("IEnumerable<T>");
}
Run Code Online (Sandbox Code Playgroud)
我想这样做:
void CallSerialize(object obj)
{
Serialize(obj as dynamic); //let the CLR resolve it at runtime.
}
Run Code Online (Sandbox Code Playgroud)
现在基于运行时类型obj,将调用正确的重载.例如,
//Test code
CallSerialize(new List<int>()); //prints IEnumerable<T>
Run Code Online (Sandbox Code Playgroud)
在这种情况下,调用第三个重载并且基本原理非常简单:这只是可行的选项.
但是,如果我这样做:
CallSerialize(new Dictionary<int,int>()); //prints IDictionary<TKey, TValue>
Run Code Online (Sandbox Code Playgroud)
它调用第一个重载.我不太明白这一点.当所有三个过载都是可行的选项时,为什么它会解决第一个过载?
实际上,如果我删除第一个,则调用第二个重载,如果我删除第一个和第二个重载,则调用第三个重载.
解决方法重载的优先顺序是什么?
由于返回类型不能用于消除方法的歧义,当你想要改变的只是返回类型时,什么是最简洁/最好的方法来重载方法?下面是一些示例代码;
public static string Get(string url, Guid id, bool logResponse = true, bool baseKey = false)
{
Tuple<string, int> response = Get(url, id, true, logResponse, baseKey);
if (response.Item2 > 399)
return null;
return response.Item1;
}
public static Tuple<string, int> Get(string url, Guid id, bool returnStatus, bool logResponse = true, bool baseKey = false)
{
// leaving out lots of code in this method, you should be able to get the point without it
int http_status;
string response = CallApi(url, key, …Run Code Online (Sandbox Code Playgroud) 我有以下程序:
#include <iostream>
namespace detail {
template <class T> char test(int T::*)
{
std::cout << "Came to one\n";
return 0;
}
template <class T> int test(...)
{
std::cout << "Came to two\n";
return 0;
}
}
struct A {};
int main()
{
detail::test<A>(0);
detail::test<int>(0);
}
Run Code Online (Sandbox Code Playgroud)
使用g ++ 4.8.2进行测试时,会产生以下输出:
Came to one Came to two
我的问题:为什么第detail::test一个电话会明确选择第一个版本?
更新
在没有第一个版本的情况下details::test,main编译好的代码.当它存在时,编译器认为它detail::test<A>()比第二个更好.
更新2
在阅读了关于成员的指针之后,即使对于不完整类型或没有指定类型的成员,也是格式良好的.,我尝试了以下,它的工作原理.
struct A;
int main()
{
detail::test<A>(0);
detail::test<int>(0);
}
Run Code Online (Sandbox Code Playgroud)
C++ 11标准有很多地方可以发现我不会想到的概念.
我有以下代码:
#include <iostream>
using namespace std;
void test(int& a) {
cout << "lvalue." << endl;
}
void test(int&& a) {
cout << "rvalue" << endl;
}
int main(int argc, char *argv[]) {
int a = 1;
int&& b = 2;
test(a);
test(1);
test(std::move(a));
test(b);
}
Run Code Online (Sandbox Code Playgroud)
哪个输出:
lvalue.
rvalue
lvalue.
lvalue.
Run Code Online (Sandbox Code Playgroud)
std::move()并且int&&是右值参考,我想知道为什么test(std::move(a))和test(b)输出lvalue?它与签名匹配和函数重载有关吗?
根据这个问题的第一个答案:函数模板重载,"非模板化(或"模板化程度较低")重载优于模板".
#include <iostream>
#include <string>
#include <functional>
void f1 (std::string const& str) {
std::cout << "f1 " << str << std::endl;
}
template <typename Callback, typename... InputArgs>
void call (Callback callback, InputArgs ...args) {
callback(args...);
}
void call (std::function<void(std::string const&)> callback, const char *str) {
std::cout << "custom call: ";
callback(str);
}
int main() {
auto f2 = [](std::string const& str) -> void {
std::cout << "f2 " << str << std::endl;
};
call(f1, "Hello World!"); …Run Code Online (Sandbox Code Playgroud) 我无法让编译器解决扩展方法的正确重载问题.我解释的最好方法是使用一些代码.这是一个演示问题的LINQPad脚本.由于我遇到的问题,这将无法编译:
void Main(){
new Container<A>().Foo(a=>false);
}
interface IMarker{}
class A : IMarker{
public int AProp{get;set;}
}
class B : IMarker{
public int BProp{get;set;}
}
class Container<T>{}
static class Extensions{
public static void Foo<T>(this T t, Func<T, bool> func)
where T : IMarker{
string.Format("Foo({0}:IMarker)", typeof(T).Name).Dump();
}
public static void Foo<T>(this Container<T> t, Func<T, bool> func){
string.Format("Foo(Container<{0}>)", typeof(T).Name).Dump();
}
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
以下方法或属性之间的调用不明确:'
Extensions.Foo<Container<A>>(Container<A>, System.Func<Container<A>,bool>)'和'Extensions.Foo<A>(Container<A>, System.Func<A,bool>)'
在我看来,它根本不含糊.第一种方法不接受a Container<T>,只接受a IMarker.似乎通用约束不能帮助解决重载,但在这个版本的代码中,它们似乎确实如下:
void Main(){
new A().Bar();
new A().Foo(a=>a.AProp == …Run Code Online (Sandbox Code Playgroud) 我想在特定的上下文中更好地理解F#重载决策.
我正在编写一个简单的asyncResult工作流程/计算表达式,以便在与异步工作流程结合使用时,以面向铁路的编程风格更容易使用错误处理.我通过Bind在工作流构建器上重载方法来完成此操作.这是相当标准的,并且在我看过的所有指南中使用(并且也用于例如Chessie/ErrorHandling.fs).
我有一个接受一个Async<_>和一个接受一个的重载Result<_,_>.现在,理想情况下,我想接受第三个重载Async<Result<_,_>>.然而,当我尝试使用let!或do!与返回表达式Async<'a>,F#抱怨独特的超载不能确定,因为这两个Async<_>和Async<Result<_,_>>配合,这当然他们这样做(虽然其中一个比另一个更适合明确).我似乎能够做到这一点的唯一方法就是像Chessie(上面的链接)那样做并定义一个包装类型:
type AsyncResult<'a, 'b> = AR of Async<Result<'a, 'b>>
Run Code Online (Sandbox Code Playgroud)
这再次要求我将所有调用包装到Async<Result<_,_>>以这种新类型返回的方法中:
asyncResult {
let! foo = funcReturningResultInsideAsync() |> AR
...
}
Run Code Online (Sandbox Code Playgroud)
AFAIK,C#将选择最具体的过载.如果F#做了同样的事情,这不会有问题.
编辑:根据评论中的要求,这里是非编译代码,显示我理想的内容,但不起作用.
module AsyncResult =
let liftAsync x =
async { return x }
let pure (value: 'a) : Async<Result<'a, 'b>> =
async { return Ok value }
let returnFrom (value: …Run Code Online (Sandbox Code Playgroud) 在与数学相关的上下文中,我想定义函数的函子<cmath>.出于这个问题的目的,我们将使用std::invoke作为我们的函子.
这是不正确的(现场演示):
std::invoke(std::sin, 0.0);
Run Code Online (Sandbox Code Playgroud)
(g ++ - 8.1)错误:没有用于调用'invoke(<unresolved overloaded function type>,double)'的匹配函数
实际上,std::sin是一个重载集,编译器缺少类型信息来选择其中一个函数.
如何从重载集中命名特定函数?我们可以取代什么LEFT,RIGHT以便以下是良好的形式,并做出预期(例如,选择double std::sin(double))?
#include <functional>
#include <cmath>
int main()
{
(void) std::invoke(LEFT std::sin RIGHT, 0.0);
}
Run Code Online (Sandbox Code Playgroud)
如果这是不可能的,有没有办法定义一个仿函数,所以它是重载集感知?