根据\xc2\xa7 12.2.2.1 [over.match.funcs.general]/9-sentence-2:
\n\n\n从类类型 C ([class.inhctor.init]) 继承的构造函数,\n其第一个参数类型为 \xe2\x80\x9c,引用 cv1 P\xe2\x80\x9d(包括从模板实例化的此类\n构造函数)当构造 cv2 D 类型的对象时,如果参数列表只有一个参数,并且 C 与 P 引用相关,并且 P 与 D 引用相关,则从候选函数集合中排除。
\n
我只是想理解这一段,并以某种方式进行一个与措辞相匹配的示例,然后我想将该示例应用于该段落:
\nstruct P;\nstruct C { C(); C(const P&); };\nstruct P : C { using C::C; };\nstruct D : P {}; \n\nD d{ P() };\nRun Code Online (Sandbox Code Playgroud)\n从上面的例子来看:C与 引用相关P和P与 引用相关D。还有一个从类类型继承的构造函数C,它的第一个参数类型为 \xe2\x80\x9c,引用cv1 P\xe2\x80\x9d。当构造一个类型的对象时cv D- 并且参数列表只有一个参数P()- 那么这个继承的构造函数将从候选函数集中排除。
我的例子与措辞的意图相符吗?我是否正确理解和解析了措辞?另外,关于这一点还有其他措辞吗(继承复制/移动构造函数)?
\nc++ using-declaration language-lawyer overload-resolution c++20
我有一个测试程序来查看编译器(g++)如何匹配模板函数:
#include<stdio.h>
template<class T>void f(T){printf("T\n");}
template<class T>void f(T*){printf("T*\n");}
template<> void f(int*){printf("int*\n");}
int main(int argc,char**) {
int *p = &argc;
f(p); // int*
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它打印int*. 看来专门的模板是高优先级匹配的?然后我稍微改变了函数声明,这次:
#include<stdio.h>
template<class T>void f(T){printf("T\n");}
template<> void f(int*){printf("int*\n");}
template<class T>void f(T*){printf("T*\n");}
int main(int argc,char**) {
int *p = &argc;
f(p); // T*
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它打印T*. 这两个程序之间的唯一区别是我稍微更改了重载“f”的函数声明,为什么结果不同?
我有一个函数模板,该函数至少接受一个参数并对其余参数执行一些格式化:
template <typename T, typename... ARGS>
void foo(T first, ARGS&&... args)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
当第一个参数是特定类型时,我希望它做不同的事情。我喜欢编译器选择这个特定的版本,其中其余的可变参数被忽略。所以我尝试了模板专业化:
template <>
void foo(const ICON* p)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
或者:
template <typename T, typename... ARGS>
void foo(const ICON* p, ARGS&&... args)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
我还尝试了非模板化重载,但它总是选择第一个版本。
调用者代码应该根本不知道模板(遗留代码、向后兼容性废话等),因此它依赖于类型推导和如下调用:
MyClass fooMaker;
fooMaker.set("A", "B", 3.14, 42); // v1
fooMaker.set(pIcon); // v2 (special)
Run Code Online (Sandbox Code Playgroud) c++ templates function-templates overload-resolution variadic-templates
我有以下代码:
struct S {
operator int(); // F1
operator double(); // F2
};
int main() {
int res = S();
}
Run Code Online (Sandbox Code Playgroud)
由于 和F1都不F2是 cv 限定的,因此隐式对象参数的类型是S&,要匹配的相应参数是S()。
现在,根据[over.match.viable]/4:(强调我的)
第三,为了使 F 成为一个可行的函数,每个参数都应该存在一个隐式转换序列,将该参数转换为 F 的相应参数。如果参数具有引用类型,则隐式转换序列包括绑定引用的操作,事实上,对非 const 的左值引用不能绑定到右值,并且右值引用不能绑定到左值,这可能会影响函数的可行性(请参阅 [over.ics.ref])。
根据上面的引用(粗体),我期望 和F1都F2不可行,因为两者的隐式对象参数都是类型,S&并且它不能绑定到右值S()。
但是,当我尝试编译代码时,我发现这两个函数都是可行的候选函数。哪个是最佳匹配不是我在这里要问的。
那么,为什么 和 都是F1可行F2的候选者,即使隐式对象参数(类型为S&)无法绑定到类纯右值S()?
我正在尝试使用概念来重载其参数取决于模板参数的模板化函数。不幸的是,这在 gcc 上失败了,报告了一个不明确的过载。
在我的项目中,我的代码在 gcc 9.3 中编译,但在 gcc 12.2 中失败。但在尝试最小化代码时,我最终得到了这个,这在两个 gcc 版本上都失败了,但在 clang 15.0.0 中有效:
#include <type_traits>
#include <iostream>
struct A
{
using value_type = int;
};
struct B
{
using value_type = int;
};
template<typename Candidate>
concept something = requires {
typename Candidate::value_type;
};
template<typename Candidate>
concept something_specific = something<Candidate> && std::is_same_v<Candidate, A>;
template<something T>
void foo()
{
std::cout << "Something" << std::endl;
}
template<something_specific T>
void foo()
{
std::cout << "Something specific" << std::endl;
} …Run Code Online (Sandbox Code Playgroud) 给出这里的代码示例:
#include <iostream>
#include <string>
class LogStream {
public:
LogStream& operator<<(int x) {
std::cout << x;
return *this;
}
LogStream& operator<<(const char* src) {
std::cout << src;
return *this;
}
};
typedef char MyType[81];
template <typename OS>
OS& operator<<(OS &os, const MyType& data) {
return os << "my version: " << data;
}
// error: use of overloaded operator '<<' is ambiguous
// (with operand types 'LogStream' and 'char const[81]')
/* LogStream& operator<<(LogStream &os, const MyType& data) {
return …Run Code Online (Sandbox Code Playgroud) 我有以下小的 C++ 代码示例,但我无法弄清楚为什么编译器以这种方式工作,尽管我花了很多时间研究 cppreference。我将不胜感激任何解释!神箭
#include <type_traits>
template<typename Tp>
struct depend_type
{
constexpr static bool false_ = false;
};
template<typename Tp>
struct cont
{
using x = void;
static_assert(std::is_same_v<Tp, int>);
// if uncomment, will be complie error -> 'cont<Tp>::x' instantiated with 'void (*p)(int) = func;'
// static_assert(depend_type<Tp>::false_);
};
template<typename Tp>
void func(Tp)
{
}
template<typename Tp>
typename cont<Tp>::x func(Tp);
int main(int /* argc */, char * /*argv*/[])
{
// func(1); is ambiguous call
void (*p)(int) = func; // why is …Run Code Online (Sandbox Code Playgroud) c++ function-templates overload-resolution template-meta-programming
是否可以为所有派生类型和模板构造函数定义构造函数?我写了这个测试用例来说明我的问题:
#include <iostream>
class Variant;
class CustomVariant;
class Variant
{
public:
Variant(void)
{}
Variant(const Variant&)
{
std::cout << "ctor" << std::endl;
}
Variant(const CustomVariant&)
{
std::cout << "custom" << std::endl;
}
template<typename T>
Variant(const T&)
{
std::cout << "template" << std::endl;
}
};
class CustomVariant : public Variant
{
};
class DerivedVariantA : public CustomVariant
{
};
class DerivedVariantB : public CustomVariant
{
};
int main(void)
{
DerivedVariantB dvb;
Variant v(dvb);
// expcected output: "custom" instead of "template"
}
Run Code Online (Sandbox Code Playgroud) 我有一个B有两个方法的类,其中一个返回指向成员变量的指针,另一个返回对该变量的const引用.
我试着打电话给那些方法.在调用期间,我将返回值存储到相应的返回类型.
我期待适当的返回类型最终会调用适当的方法,但我得到一个编译错误说:
error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive] const int& refval2 = b.Get(); `
这是我的代码:
#include <iostream>
class B{
public:
int* Get(){
return &x_;
}
const int & Get() const{
return x_;
}
private:
int x_ = 0;
};
int main(){
B b;
const int& refval2 = b.Get();
int* pval2 = b.Get();
}
Run Code Online (Sandbox Code Playgroud) 我有2个都具有单参数模板化构造函数的类。一个是整数类型的全部,另一个是用于绑定任何可迭代对象的。对于每种类型的特定函数,我都有两个重载。如果我使用整数类型或字符串或对至少一个类有用的函数来调用函数,则会收到有关调用歧义的错误。
#include <string>
class A {
public:
template <typename Iterable>
A(Iterable it) : s(it.begin(), it.end()) {}
private:
std::string s;
};
class B {
public:
template <typename Integer>
B(Integer i) : i(i + 1) {}
private:
int i;
};
void Use(A a)
{
// some thing
}
void Use(B b)
{
// some other thing
}
int main(void)
{
Use(0);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器似乎对多态集的关注程度还不足以确定确实只有一种可能的解决方案。难道是因为在函数重载之前“解析了”模板吗?如何给编译器一些帮助?