请考虑以下代码:
#include <iostream>
#include <type_traits>
// Variadic version
template<class... Variadic>
void f(const Variadic&... variadic)
{
std::cout<<"variadic"<<std::endl;
}
// Single version
template<class Single, class = typename std::enable_if<std::is_fundamental<Single>::value>::type>
void f(const Single& single)
{
std::cout<<"single"<<std::endl;
}
// Main
int main()
{
f(); // variadic
f(42); // single : why?
f(std::string()); // variadic
f(42, 42); // variadic
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我不明白为什么标记为"单一"的行编译得很好(在g ++ 4.6.3下)并且不会产生重载解析问题.c ++ 11标准是否说具有固定数量参数的模板函数优先于可以具有相同签名的可变参数函数?
c++ standards-compliance overload-resolution variadic-templates c++11
我想知道如何编译这段代码:
// test3.cpp
#include <iostream>
using namespace std;
template<typename R, typename... rArgs>
R universal_exer(R(*f)(rArgs...), rArgs... args)
{
return (*f)(forward<rArgs>(args)...);
}
int addition(int a)
{
return a;
}
int addition(int a, int b)
{
return a + b;
}
template<typename... Args>
int addition(int a, int b, Args... args)
{
return a + b + addition(args...);
}
int main()
{
cout << universal_exer(&addition, 1) << endl;
}
Run Code Online (Sandbox Code Playgroud)
错误消息(gcc 4.7.2):
test3.cpp: In function 'int main()':
test3.cpp:31:40: error: no matching function for call to …Run Code Online (Sandbox Code Playgroud) 我有两个重载的泛型方法:
T Foo<T>(T t) { Console.WriteLine("T"); return t; }
T Foo<T>(int i) { Console.WriteLine("int"); return default(T); }
Run Code Online (Sandbox Code Playgroud)
当我尝试Foo在我的电脑上调用如下:
Foo(5);
Run Code Online (Sandbox Code Playgroud)
我没有编译器错误或警告,并调用带泛型参数的第一个方法(即输出T).在所有C#化身和所有平台上都会出现这种情况吗?在那种情况下,为什么?
另一方面,如果我在泛型调用中明确指定类型:
Foo<int>(5);
Run Code Online (Sandbox Code Playgroud)
调用带参数的第二个方法int,即输出现在int.为什么?
我在两个方法重载中使用不同的参数名称,因此以下调用的输出是预期的:
Foo<int>(t: 5); // output 'T'
Foo<int>(i: 5); // output 'int'
Run Code Online (Sandbox Code Playgroud)
如果我调用第一种方法,我甚至可以省略类型规范:
Foo(t: 5); // output 'T'
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试编译这个:
Foo(i: 5);
Run Code Online (Sandbox Code Playgroud)
我得到一个错误方法'Foo(int)'的类型参数不能从用法中推断出来.尝试显式指定类型参数. 为什么编译器不能处理这个调用?
注意这些测试是在Windows 8 x64系统上使用LinqPad执行的(如果与结果相关...)
你能解释一下STL容器如何使用空的初始化列表处理赋值运算符?
当我做这样的事情:
vector<int> v;
v = { };
Run Code Online (Sandbox Code Playgroud)
被调用的函数不是:
vector& operator= (initializer_list<value_type> il);
Run Code Online (Sandbox Code Playgroud)
但:
vector& operator= (vector&& x);
Run Code Online (Sandbox Code Playgroud)
另一方面,当我和我自己的班级做类似的事情时:
struct A {
A& operator= (const A&) { return *this; }
A& operator= (A&&) { return *this; }
A& operator= (initializer_list<int>) { return *this; }
};
/* ... */
A a;
a = { };
Run Code Online (Sandbox Code Playgroud)
代码不能在VS2013上编译,并说:
error C2593: 'operator =' is ambiguous
Run Code Online (Sandbox Code Playgroud)
如果列表不为空,它工作正常,它只是用初始化列表调用函数.只有当列表为空时才会出现问题,在向量上调用rvalue赋值运算符,在我的类上它会给出错误.
如何在向量和其他容器中处理这种情况?
c++ initializer-list overload-resolution compiler-bug visual-studio-2013
请考虑以下代码:
public class Tests
{
public void Test()
{
Assert.AreEqual("Int", DoSomething(1));
}
public static string DoSomething<T>(T value)
{
return "Generic";
}
public static string DoSomething(int value)
{
return "Int";
}
}
Run Code Online (Sandbox Code Playgroud)
正如所料,将调用非泛型的DoSomething方法.现在考虑以下修改:
public class Tests
{
public void Test()
{
Assert.AreEqual("Int", DoSomething(1));
}
public static string DoSomething<T>(T value)
{
return "Generic";
}
public static string DoSomething<T>(int value)
{
return "Int";
}
}
Run Code Online (Sandbox Code Playgroud)
我唯一改变的是将T类型参数添加到第二个重载,从而使其成为通用的.请注意,不使用type参数.
该修改导致调用第一个DoSomething方法.为什么?编译器具有所需的所有信息,以便选择第二种方法.
你能解释为什么,甚至更好地指出我解释这种行为的C#规范部分?
这是我的代码段:
class Base{};
class Derived : private Base{};
template<class T>
class Wrapper
{
public:
template<typename T2>
Wrapper( T2&& )
{ }
};
// Function declarations
void func( Base& param );
void func( Wrapper<Derived> );
void funcUnambiguous( Wrapper<Derived> );
// Here is the Call:
Derived d = Derived();
func( d ); // <- Error
Run Code Online (Sandbox Code Playgroud)
GCC 4.9给了我: error: 'Base' is an inaccessible base of 'Derived'
而我这样做
Derived d = Derived();
funcUnambiguous( d );
Run Code Online (Sandbox Code Playgroud)
它只是工作正常.
看起来,任何只需要廉价演员的功能,即使是格式错误,也隐藏着隐含但昂贵的演员功能.有人有线索吗?
我有点困惑.让我们假设我有一个帮助类Data
class Data
{
public:
Data(const QVariant &value) : m_Variant(value) { }
operator QString() const { return m_Variant.toString(); }
private:
QVariant m_Variant;
};
Run Code Online (Sandbox Code Playgroud)
那时当我这样做:
Data d("text");
QString str = d; //str becomes "text"
Run Code Online (Sandbox Code Playgroud)
它有效,但当我继续做:
Data d2("text2");
str = d2; //does not compile
Run Code Online (Sandbox Code Playgroud)
抱怨失败:
ambiguous overload for 'operator=' (operand types are 'QString' and 'Data')
candidates are:
...
QString &operator=(const QString &);
QString &operator=(QString &&);
QString &operator=(const char*); <near match>
no known conversion from Data to const char*
QString &operator=(char);
Run Code Online (Sandbox Code Playgroud)
但即使提供 …
c++ qt conversion-operator overload-resolution implicit-conversion
阅读了一篇很棒的文章真实的故事:高效的包装我试着自己实现元组作为练习:
#include <type_traits>
#include <utility>
#include <functional>
template< std::size_t I, typename T >
struct tuple_leaf { T value; };
template< std::size_t I, typename T >
T & get(tuple_leaf< I, T > & leaf)
{ return leaf.value; }
template< typename Is, typename ...Ts >
struct tuple_base;
template< std::size_t ...Is, typename ...Ts >
struct tuple_base< std::index_sequence< Is... >, Ts... >
: tuple_leaf< Is, Ts >...
{
using tuple_base_t = tuple_base;
template< typename ...Args, typename = std::enable_if_t< (sizeof...(Ts) == sizeof...(Args)) > …Run Code Online (Sandbox Code Playgroud) 下面的代码演示了我用来确定某个类型是否T是特定类模板的实例化的C++模板元编程模式的核心:
#include <iostream>
template<class A, class B>
struct S{};
template<class A, class B>
constexpr bool isS(const S<A,B>*) {return true;}
template<class T>
constexpr bool isS(const T*) {return false;}
int main() {
S<int,char> s;
std::cout<<isS(&s)<<std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它具有两个constexpr功能模板的重载,并按预期isS输出1.如果我从第二个删除指针isS,即替换它
template<class T>
constexpr bool isS(const T) {return false;}
Run Code Online (Sandbox Code Playgroud)
该程序意外输出0.如果两个版本isS都通过编译的重载决策阶段,那么输出意味着编译器正在选择第二个重载.我已经在海湾合作委员会,并锵VC++使用在线编译器测试了这里,他们都产生相同的结果.为什么会这样?
我已多次阅读Herb Sutter的"为什么不专攻功能模板"一文,似乎这两个isS功能都应该被认为是基本模板.如果是这样,那么问题是哪一个是最专业的.通过直觉和这个答案,我希望第一个isS是最专业的,因为T可以匹配每个实例化S<A,B>*,并且有许多可能的实例化T无法匹配S<A,B>*.我想在工作草案中找到定义此行为的段落,但我不完全确定编译的哪个阶段会导致问题.是否与 …
c++ pointers function-templates overload-resolution argument-deduction
我有这么短的代码片段,我希望得到更多关于为什么重载决策选择一个构造函数而不是另一个构造函数的信息.这是有问题的代码:
#include <iostream>
struct Base
{
};
struct Other
{
Other(const Other&)
{
std::cout << "Copy Constructor\n";
}
Other(const Base&)
{
std::cout << "Custom Constructor\n";
}
};
struct Derived : public Base, public Other
{
Derived() :
Other(*this)
{
}
};
int main()
{
Derived derived; // Prints "Copy Constructor"
system("pause");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我假设C++标准中有一节将复制构造函数定义为比用户定义的构造函数更好的匹配*?我的另一个假设是,如果没有任何规则支持复制构造函数,那么编译器要么按照继承的顺序(如同具有多重继承的构造顺序),要么只是给我一个模糊的构造函数调用错误.但是,颠倒了Derived继承Base和Other不改变输出的顺序,这让我相信我最初关于复制构造函数的猜测是正确的.任何人都能指出我决定我所看到的行为的规则吗?
*我查看了cppreference.com的Overload Resolution页面,但我没有看到任何列出的规则可以解释我所看到的行为(虽然我不能完全熟悉Standardese,所以我很容易错过它).
c++ inheritance constructor multiple-inheritance overload-resolution
c++ ×8
c++11 ×4
c# ×2
generics ×2
ambiguity ×1
compiler-bug ×1
constructor ×1
inheritance ×1
malformed ×1
overloading ×1
pointers ×1
qt ×1
templates ×1