假设我有以下Data课程:
struct Data {
char foo[8];
char bar;
};
Run Code Online (Sandbox Code Playgroud)
和以下函数,my_algorithm需要一对char *(类似于STL算法):
void my_algorithm(char *first, char *last);
Run Code Online (Sandbox Code Playgroud)
对于Data的foo数据成员,而不是my_algorithm()像这样调用:
Data data;
my_algorithm(data.foo, data.foo + 8);
Run Code Online (Sandbox Code Playgroud)
我可以使用std::begin()和std::end()便利功能模板:
my_algorithm(std::begin(data.foo), std::end(data.foo));
Run Code Online (Sandbox Code Playgroud)
我想实现类似于Data的bar数据成员的功能。也就是说,而不是写:
my_algorithm(&data.bar, &data.bar + 1);
Run Code Online (Sandbox Code Playgroud)
我想写一些像:
my_algorithm(begin(data.bar), end(data.bar));
Run Code Online (Sandbox Code Playgroud)
因此,在这种情况下,我定义了以下两个普通(非模板)函数:
char* begin(char& c) { return &c; }
char* end(char& c) { return &c + 1; }
Run Code Online (Sandbox Code Playgroud)
这样我就可以编写如下代码:
Data data;
using std::begin;
using std::end;
my_algorithm(begin(data.foo), end(data.foo)); …Run Code Online (Sandbox Code Playgroud) 例如,GCC和clang都无法编译以下代码:
struct S {};
namespace N
{
void g(S);
}
using N::g;
namespace N
{
void g(int);
}
int main()
{
g(0);
}
Run Code Online (Sandbox Code Playgroud)
有错误:
test.cpp: In function 'int main()':
test.cpp:17:8: error: could not convert '0' from 'int' to 'S'
g(0);
^
Run Code Online (Sandbox Code Playgroud)
建议using声明仅导入在using声明出现点之上声明的重载,而不是稍后出现的(但在使用名称之前).
这种行为是否正确?
在GCC 4.6中,即使由于移动构造函数而隐式删除子节点的赋值运算符,也可以继承父节点的赋值运算符.在GCC的后续版本(以及Clang)中,这已不再可能.让子类使用父类赋值运算符的正确方法是什么?
struct A
{
A & operator=(A const & other) = default;
};
struct B : public A
{
B() {}
B(B && other) {}
using A::operator=;
};
int main()
{
B b1, b2;
b1 = b2; // error: use of deleted function because B's operator= is implicitly deleted due to move constructor
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我有一个看起来或多或少像这样的功能:
template<class C> auto f(C const& c) -> decltype(begin(c)){
using std::begin;
return begin(c);
}
Run Code Online (Sandbox Code Playgroud)
函数的主体利用" using和使用"成语和
感谢decltypeSFINAE,如果返回类型无效.
然而,它一般来说并不完美,因为我无法告诉它decltype有using std声明begin.
template<class C> auto f(C const& c) -> decltype(std::begin(c))
Run Code Online (Sandbox Code Playgroud)
也会不一致,例如何时decltype(c)和begin属于不同的命名空间.
周围有路吗?
理想情况下,我想要类似的东西
template<class C> auto f(C const& c) -> decltype(using std::begin; begin(c))
Run Code Online (Sandbox Code Playgroud)
我认为lambda原则上可以工作
template<class C> auto f(C const& c) -> decltype([&]{using std::begin; return begin(c)})
Run Code Online (Sandbox Code Playgroud)
但是内部禁止使用lambdas decltype.
在GCC中有一个有趣的语言扩展("表达式语句")是有希望的,但是它不能在函数体外工作(与未评估的上下文中不允许使用lambda). 否则它将是一个解决方案.
template<class C> auto g(C const& c)
->decltype(({using std::begin; begin(c);})){ …Run Code Online (Sandbox Code Playgroud) c++ decltype using-declaration argument-dependent-lookup c++11
从C++ 11开始,可以有两个复制构造函数,一个采用类型参数,另一个采用类型T&参数const T&.
我有一种情况,即(似乎)添加第二个复制构造函数会导致在构造函数在派生类中继承时不会调用任何一个.当两者都存在时,复制构造函数被模板化构造函数覆盖.
这是一个MWE:
struct A {
template <typename... Args>
A (Args&&... args)
{ std::cout << "non-default ctor called\n"; }
A (A&) { std::cout << "copy ctor from non-const ref\n"; }
};
struct C :public A { using A::A; };
int main() {
C c1;
C c2(c1);
}
Run Code Online (Sandbox Code Playgroud)
运行此代码,我们看到输出
non-default ctor called
copy ctor from non-const ref
Run Code Online (Sandbox Code Playgroud)
这是预期的.
但是,添加一个额外的构造函数struct A如下:
A (const A&) { }
Run Code Online (Sandbox Code Playgroud)
以某种方式导致其他复制构造函数不被调用,因此输出变为
non-default ctor called …Run Code Online (Sandbox Code Playgroud) 我想定义一个类,它继承了一堆类,但不隐藏这些类的某些特定方法。
想象一下下面的代码:
template<typename... Bases>
class SomeClass : public Bases...
{
public:
using Bases::DoSomething...;
void DoSomething(){
//this is just another overload
}
};
Run Code Online (Sandbox Code Playgroud)
现在的问题是,如果只有一个类没有具有该名称的成员,DoSomething我会收到错误。我已经尝试过使用宏和 SFINAE 来模拟“如果未定义则忽略”,但要处理所有情况,这会变得非常大且丑陋!你有什么办法解决这个问题吗?
如果我可以定义:“嘿使用 - 忽略缺失的成员”,那就太好了。
这里我有一些示例代码:Godbolt
template<typename>
struct A
{
int n;
A(bool)
{}
};
template<typename>
struct B
{
struct C : A<B>
{
using Base = A<B>;
using A<B>::A; // ok
using Base::n; // ok
// error: dependent using declaration resolved to type without 'typename'
using Base::A;
};
C get() const
{
return C(true);
}
};
int main()
{
auto b = B<int>();
b.get();
}
Run Code Online (Sandbox Code Playgroud)
错误已在代码中描述。
为什么不能使用 typedef 类型来声明其父类的构造函数?
我在使用名称空间时遇到歧义问题。
代码:
namespace app::hal {
enum class Motor {
Left = 0,
Right = 1
};
void setMotor(Motor which, float duty);
}
namespace app::control {
using Motor = app::hal::Motor;
void setMotor(Motor which, float duty);
float getMotor(Motor which);
}
inline void test() {
using app::control::setMotor;
using app::control::Motor;
setMotor(Motor::Left, 0);
}
Run Code Online (Sandbox Code Playgroud)
错误:
<source>:24:17: error: call of overloaded 'setMotor(app::hal::Motor, int)' is ambiguous
24 | setMotor(Motor::Left, 0);
| ~~~~~~~~^~~~~~~~~~~~~~~~
<source>:15:14: note: candidate: 'void app::control::setMotor(Motor, float)'
15 | void setMotor(Motor which, float duty);
| ^~~~~~~~ …Run Code Online (Sandbox Code Playgroud) 有没有办法将模板参数"捆绑"在一起以避免重复?
我有几个类和函数都使用相同的三个模板参数.拥有一次使用每个类/函数的函数并不罕见.结果代码非常快速地变得非常混乱.是否有更简洁的方法来编写此代码?
// ContextFactory is a pointer to functions that instantiate objects that are subtypes of MetricContext
template<typename VertexID, typename EdgeMembershipType, typename SetBitmap>
using ContextFactory = MetricContext <VertexID, EdgeMembershipType, SetBitmap> *(*)(const char *);
template<typename VertexID, typename EdgeMembershipType, typename SetBitmap>
static vector<ContextFactory<VertexID, EdgeMembershipType, SetBitmap>> buildCFList() {
vector<ContextFactory<VertexID, EdgeMembershipType, SetBitmap>> answer;
answer.push_back(MetricContext<VertexID, EdgeMembershipType, SetBitmap>::template make<NeoContext<VertexID, EdgeMembershipType, SetBitmap >>);
return answer;
};
Run Code Online (Sandbox Code Playgroud)
请注意,此函数的近一半是字符串的重复<VertexID, EdgeMembershipType, SetBitmap>>,但每次使用此字符串都适用于不同的类或函数,因此我认为别名不起作用.
(如果它有帮助,这个函数的目的是创建一个指向函数的指针数组,这些函数将创建作为子类型的子对象的对象 MetricContext<VertexID, EdgeMembershipType, SetBitmap>>
下面的代码
#include <vector>
#include <string>
template<typename T>
struct V : public std::vector<T>
{
using Impl = std::vector<T>;
using typename Impl::vector; // the constructors
};
int main()
{
std::string empty;
V<std::string> meow{42UL, empty};
}
Run Code Online (Sandbox Code Playgroud)
由 GCC 8.2 编译良好(调用size_t, string构造函数)。然而, clang up to 14 拒绝它
<source>:14:20: error: no matching constructor for initialization of 'V<std::string>' (aka 'V<basic_string<char>>')
V<std::string> meow{42UL, empty};
^ ~~~~~~~~~~~~~
<source>:5:8: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
struct V …Run Code Online (Sandbox Code Playgroud) c++ ×10
c++11 ×6
inheritance ×3
namespaces ×2
overloading ×2
templates ×2
c++17 ×1
c++20 ×1
constructor ×1
decltype ×1
move ×1
name-hiding ×1
scope ×1
typedef ×1