我想知道以下是否可行.创建一个接受匿名类型(string,int,decimal,customObject等)的类,然后重载方法根据Type执行不同的操作.例
class TestClass<T>
{
public void GetName<string>()
{
//do work knowing that the type is a string
}
public string GetName<int>()
{
//do work knowing that the type is an int
}
public string GetName<int>(int addNumber)
{
//do work knowing that the type is an int (overloaded)
}
public string GetName<DateTime>()
{
//do work knowing that the type is a DateTime
}
public string GetName<customObject>()
{
//do work knowing that the type is a customObject type
}
}
Run Code Online (Sandbox Code Playgroud)
所以现在我可以调用GetName方法,因为我在初始化对象时已经传入了类型,所以找到并执行了正确的方法.
TestClass …Run Code Online (Sandbox Code Playgroud) 请考虑以下最小示例:
#include <iostream>
using namespace std;
class myostream : public ostream {
public:
myostream(ostream const &other) :
ostream(other.rdbuf())
{ }
};
int main() {
cout << "hello world" << endl;
myostream s(cout);
s << "hello world" << endl;
myostream(cout) << "hello world" << endl;
}
Run Code Online (Sandbox Code Playgroud)
g ++和Visual C++上的输出都是
hello world
hello world
0x4012a4
Run Code Online (Sandbox Code Playgroud)
写入临时对象的版本myostream(cout)似乎更喜欢成员运算符ostream::operator<<(void *),而不是自由运算符operator<<(ostream &, char *).对象是否有名称似乎有所不同.
为什么会这样?我该如何防止这种行为?
编辑:为什么它发生现在从各种答案清楚.至于如何防止这种情况,以下似乎很吸引人:
class myostream : public ostream {
public:
// ...
myostream &operator<<(char const *str) …Run Code Online (Sandbox Code Playgroud) c++ operator-overloading member-functions overload-resolution
我在Scala中有这个类:
object Util {
class Tapper[A](tapMe: A) {
def tap(f: A => Unit): A = {
f(tapMe)
tapMe
}
def tap(fs: (A => Unit)*): A = {
fs.foreach(_(tapMe))
tapMe
}
}
implicit def tapper[A](toTap: A): Tapper[A] = new Tapper(toTap)
}
Run Code Online (Sandbox Code Playgroud)
现在,
"aaa".tap(_.trim)
Run Code Online (Sandbox Code Playgroud)
不编译,给出错误
错误:扩展函数缺少参数类型((x $ 1)=> x $ 1.trim)
为什么不推断类型String?从错误看来,隐式转换似乎触发了(否则错误将沿着" tap不是类的成员String"的行).似乎转换必须是Tapper[String],这意味着参数的类型是String => Unit(或(String => Unit)*).
有趣的是,如果我注释掉任何一个tap定义,那么它就会编译.
以下内容无法编译clang35 -std=c++11:
#include <iostream>
#include <string>
#include <initializer_list>
class A
{
public:
A(int, bool) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
A(int, double) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
A(std::initializer_list<int>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
int main()
{
A a1 = {1, 1.0};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有错误
init.cpp:15:14: error: type 'double' cannot be narrowed to 'int' in initializer list [-Wc++11-narrowing]
A a1 = {1, 1.0};
^~~
init.cpp:15:14: note: insert an explicit cast to silence …Run Code Online (Sandbox Code Playgroud) 我有一个真实的情况,可以在下面的例子中总结:
template< typename ListenerType >
struct Notifier
{
void add_listener( ListenerType& ){}
};
struct TimeListener{ };
struct SpaceListener{ };
struct A : public Notifier< TimeListener >
, public Notifier< SpaceListener >
{
};
struct B : TimeListener{ };
int main()
{
A a;
B b;
a.add_listener( b ); // why is ambiguous?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器不明显B是a TimeListener,因此唯一可能的重载解决方案是Notifier< TimeListener >::add_listener( TimeListener& )?
c++ multiple-inheritance overload-resolution name-lookup template-classes
在下面的代码中(在coliru上直播):
#include <iostream>
#include <string>
int main()
{
struct S {
operator bool () const { return false; }
operator std::string () const { return "false"; }
} s;
std::cout << s << "\n"; // outputs 0
}
Run Code Online (Sandbox Code Playgroud)
编译器如何选择隐式转换为boolover std::string?
我的假设是,在这种情况下,它可能纯粹是不同口味的宣告顺序std::basic_ostream::operator<<,但这一切都是什么?标准是否说明了选择特定的隐式转换?
c++ standards casting operator-overloading overload-resolution
请考虑以下代码段:
#include <iostream>
#include <vector>
void f(std::vector<int>){std::cout << __PRETTY_FUNCTION__ << '\n';}
void f(int x){std::cout << __PRETTY_FUNCTION__ << '\n';}
int main()
{
f({42});
}
Run Code Online (Sandbox Code Playgroud)
如果你运行它,你可以看到f(int)重载是首选,即使std::vector有一个std::initializer_list构造函数(见#8).
问题:为什么转换{42}为int首选(而不是转换为std::vector,{42}是std::initializer_list)?
我今天意识到这个编译并运行良好:
public class Test {
public static <T> T handle(T val) {
System.out.println("T");
return val;
}
public static <T extends String> T handle(T val) {
System.out.println("T extends String");
return val;
}
}
Run Code Online (Sandbox Code Playgroud)
这两个handle方法具有相同的名称,并且?参数的数量和类型()相同.唯一的区别是第二种handle方法具有更严格的通用界限.IDE根本没有抱怨,代码编译得很好.在运行时方法按预期选择 - 例如,Test.handle("this is a string")将调用第二个方法Test.handle(10)并将调用第一个方法.
泛型绑定是否被认为是方法签名的一部分?或者它是一种方法重载决议魔术?
可以看到在下面的代码中,带有int参数的构造函数被调用。我知道int这很好。但是为什么不short呢?的ASCII值作为'A'65 short可以容纳一个。
在什么条件下int调用带有数据类型参数的构造函数?
#include<iostream>
class RightData
{
int x;
public:
RightData(short data)
{
cout<< "Short" << endl;
}
RightData(int data)
{
cout<< "Int" << endl;
}
RightData(float data)
{
cout<< "Float" << endl;
}
~RightData()
{
cout<< "Final";
}
};
int main()
{
RightData *ptr = new RightData('A');
return 0;
}
Run Code Online (Sandbox Code Playgroud) 以下代码无法编译(Godbolt 链接):
#include <concepts>
template <class Fn>
decltype(auto) g(Fn&& fn) { return fn(); }
template <typename T>
requires(std::integral<T>) int f() { return 0; }
template <typename T>
int f() { return 1; }
int main() {
f<int>();
f<void>();
g(f<int>); // error: invalid initialization of non-const reference of type 'int (&)()'
// from an rvalue of type '<unresolved overloaded function type>'
g(f<void>);
}
Run Code Online (Sandbox Code Playgroud)
对我来说,似乎出乎意料的是,调用时重载解析会成功f<int>()(选择受约束的版本作为比不受约束的版本更好的匹配),但作为f<int>参数传递时会失败。
请注意,将无约束版本更改为不相交约束确实可以编译(Godbolt 链接):
#include <concepts>
template <class Fn>
decltype(auto) g(Fn&& …Run Code Online (Sandbox Code Playgroud) c++ ×7
c++11 ×3
overloading ×3
types ×2
c# ×1
c++-concepts ×1
c++20 ×1
casting ×1
constructor ×1
generics ×1
java ×1
name-lookup ×1
scala ×1
standards ×1