是否可以专门化模板类的特定成员?就像是:
template <typename T,bool B>
struct X
{
void Specialized();
};
template <typename T>
void X<T,true>::Specialized()
{
...
}
template <typename T>
void X<T,false>::Specialized()
{
...
}
Run Code Online (Sandbox Code Playgroud)
当然,这段代码无效.
我创建了一个模板如下
template<typename T>
void f(T const& t) { }
Run Code Online (Sandbox Code Playgroud)
我希望这可以通过容器调用,也可以通过初始化列表调用.我认为这将是initializer_list<int>
,如下调用.
f({1, 2, 3});
Run Code Online (Sandbox Code Playgroud)
但GCC表现得好像不符合标准
m.cpp: In function 'int main()':
m.cpp:6:25: warning: deducing 'const T' as 'const std::initializer_list<int>'
m.cpp:4:6: warning: in call to 'void f(const T&) [with T = std::initializer_list<int>]'
m.cpp:6:25: warning: (you can disable this with -fno-deduce-init-list)
Run Code Online (Sandbox Code Playgroud)
谁能解释我如何在没有警告的情况下完成这项工作?谢谢!
我最近遇到了初始化列表的一些问题.考虑一个存储类似地图数据的程序
struct MyMapLike {
MyMapLike(std::map<std::string, int> data)
:data(std::move(data))
{ }
private:
std::map<std::string, int> data;
};
Run Code Online (Sandbox Code Playgroud)
这看起来很直接.但是在初始化时,它会变得难看.我想让它看起来像
MyMapLike maps = { { "One", 1 }, { "Two", 2 } };
Run Code Online (Sandbox Code Playgroud)
但是编译器并不想接受这一点,因为上面意味着它应该寻找一个两个参数的构造函数,可以接受{ "One", 1 }
和{ "Two", 2 }
分别.我需要添加额外的大括号,使它看起来像一个单参数构造函数接受{ { ... }, { ... } }
MyMapLike maps = { { { "One", 1 }, { "Two", 2 } } };
Run Code Online (Sandbox Code Playgroud)
我不想那样写.由于我有类似map的类,并且初始化程序具有映射列表的抽象值,因此我想使用前一版本,并且独立于任何此类实现细节,例如构造函数的嵌套级别.
一个解决方法是声明一个初始化列表构造函数
struct MyMapLike {
MyMapLike(std::initializer_list<
std::map<std::string, int>::value_type
> vals)
:data(vals.begin(), vals.end())
{ }
MyMapLike(std::map<std::string, int> data) …
Run Code Online (Sandbox Code Playgroud) 我一直在查看C++ 0x的N3291工作草案.我对extern模板感到好奇.第14.7.3节规定:
除了内联函数和类模板特化之外,显式实例化声明具有抑制它们引用的实体的隐式实例化的效果.
仅供参考:"明确的实例化声明"一词是标准的extern template
.这已在第14.7.2节中定义.
这听起来像是在说如果你使用extern template std::vector<int>
,那么做任何通常隐式实例化的事情std::vector<int>
都不会这样做.
下一段更有趣:
如果实体是同一翻译单元中的显式实例化声明和显式实例化定义的主题,则该定义应遵循声明.作为显式实例化声明的主体并且以在否则将导致翻译单元中的隐式实例化(14.7.1)的方式中使用的实体应该是程序中某处的显式实例化定义的主题; 否则该程序格式错误,无需诊断.
仅供参考:术语"显式实例化定义"是这些事物的标准说法:template std::vector<int>
.也就是说,没有了extern
.
对我来说,这两件事说extern template
防止了隐式实例化,但它并没有阻止显式实例化.所以,如果你这样做:
extern template std::vector<int>;
template std::vector<int>;
Run Code Online (Sandbox Code Playgroud)
第二行有效地否定了第一行,明确地做了第一行隐含发生的事情.
问题是:Visual Studio 2008似乎不同意.我想要使用的方法extern template
是阻止用户隐式实例化某些常用模板,以便我可以在.cpp文件中显式实例化它们以减少编译时间.模板只会实例化一次.
问题是我必须在VS2008中围绕它们#ifdef.因为如果单个翻译单元看到extern
和非extern
版本,它将使extern
版本获胜并且没有人会实例化它.然后是链接器错误.
所以,我的问题是:
extern template
防止明确的实例化吗?extern template
行为?c++ templates visual-studio-2008 explicit-instantiation c++11
在C++ 0x中,简化了SFINAE规则,使得在演绎的"直接上下文"中出现的任何无效表达式或类型不会导致编译器错误,而是导致演绎失败(SFINAE).
我的问题是:
如果我采用重载函数的地址并且无法解决,那么在演绎的直接上下文中是否会失败?
(如果它无法解决,那么它是一个硬错误还是SFINAE)?
以下是一些示例代码:
struct X
{
// template<class T> T* foo(T,T); // lets not over-complicate things for now
void foo(char);
void foo(int);
};
template<class U> struct S
{
template<int> struct size_map
{ typedef int type; };
// here is where we take the address of a possibly overloaded function
template<class T> void f(T,
typename size_map<sizeof(&U::foo)>::type* = 0);
void f(...);
};
int main()
{
S<X> s;
// should this cause a compiler error because 'auto T = &X::foo' …
Run Code Online (Sandbox Code Playgroud) 它刚好发生在我身上,我想知道在下列情况下如何释放资源.
class Base {
Resource *r;
public:
Base() { /* ... */ }
~Base() {
delete r;
}
};
class Derived : public Base {
public:
Derived() { /* ... */ }
~Derived() {
/* Suddenly something here throws! */
}
};
int main() {
try {
Derived d;
} catch(...) {
/* what happened with Base::r !? */
}
}
Run Code Online (Sandbox Code Playgroud)
如果派生类析构函数抛出,是否会调用基类析构函数?或者会有泄漏吗?
我得到了很多关于交换机的警告,这些交换机仅部分覆盖了切换的枚举范围.为此,我想有一个"默认"所有这些开关,并将__builtin_unreachable
(GCC内置),在这种情况下,让编译器知道这种情况是不可达.
但是,我才知道GCC4.3还不支持内置版.有没有什么好方法可以模仿这个功能?我考虑过取消引用空指针,但这可能有其他不良影响/警告等.你有更好的主意吗?
我和一位同事进行了这次谈话,结果很有趣.假设我们有以下POD课程
struct A {
void clear() { memset(this, 0, sizeof(A)); }
int age;
char type;
};
Run Code Online (Sandbox Code Playgroud)
clear
旨在清除所有成员,设置为0
(按字节顺序).如果我们A
用作基类会出现什么问题?这里有一个微妙的漏洞来源.