我有一个模板类,看起来像这样:
template<class T> class C
{
void A();
void B();
// Other stuff
};
template<class T> void C<T>::A() { /* something */ }
template<class T> void C<T>::B() { /* something */ }
Run Code Online (Sandbox Code Playgroud)
我想要的是仅A在保留默认值B和"其他内容"时提供显式特化.
到目前为止我尝试过的是
class D { };
template<> void C<D>::A() { /*...*/ } // Gives a link error: multiple definition
Run Code Online (Sandbox Code Playgroud)
我尝试过的每个其他变体都会因解析错误而失败.
最初的问题是显式特化是在头文件中,因此它被转储到几个目标文件中并弄乱了链接(为什么链接器没有注意到符号的所有实例都是相同的只是闭嘴?)
解决方案最终是将显式特化从头文件移动到代码文件.但是为了使头文件的其他用户不是默认版本的实例,我需要将原型放回头部.然后为了让GCC实际生成显式特化,我需要在代码文件中放置一个正确类型的虚拟变量.
我正在编写一个类,它有一个自己类型的unordered_set作为成员.因此我需要写一个专业化hash<Foo>.在声明Foo之后需要定义此特化.但在我看来,好像hash<Foo>在定义成员之前我已经需要专门化了unordered_set<Foo>.至少它不会编译并在那里失败.我尝试了哈希模板的前向声明,但无法使其工作.
相关的代码段是:
class Foo {
public:
int i;
std::unordered_set<Foo> dummy;
Peer(std::unordered_set<Foo>);
};
namespace std {
template<> struct hash<Foo>
{
size_t operator()(const Foo& f) const
{
return hash<int>()(f.i);
}
};
}
Run Code Online (Sandbox Code Playgroud)
提前致谢
我重复上一个问题的代码,使这个问题自成一体.如果使用gcc 4.8.3编译,下面的代码将编译并不会发出任何警告.与-std=c++1y.但是,如果使用-std=c++0xflag 编译,它会发出警告.在前一个问题的上下文中,声明代码不使用gcc 4.9.0进行编译.不幸的是,目前我还不完全了解如何auto实施.因此,如果有人能回答以下问题,我将不胜感激:
1).对于C++ 14标准,代码下面的代码是否有效?
2).如果是的话,这段代码会被认为是一种好的风格吗?如果没有,为什么不呢?
3).为什么下面的代码在使用C++ 11编译器时编译和工作(有时)?或者,为什么它不总是有效?是否有任何特定的标志/选项/设置可能阻止它工作?
template<int N> auto getOutputPort2();
template<> auto getOutputPort2<0>();
template<> auto getOutputPort2<1>();
template<>
auto getOutputPort2<0>()
{
return std::unique_ptr<int>(new int(10));
}
template<>
auto getOutputPort2<1>()
{
return std::unique_ptr<string>(new string("qwerty"));
}
Run Code Online (Sandbox Code Playgroud) template <typename T>
bool validate(const T& minimum, const T& maximum, const T& testValue) {
return testValue >= minimum && testValue <= maximum;
}
template <>
bool validate<const char&>(
const char& minimum,
const char& maximum,
const char& testValue)
{
char a = toupper(testValue);
char b = toupper(minimum);
char c = toupper(maximum);
return a >= b && a <= c;
}
Run Code Online (Sandbox Code Playgroud)
这是函数模板,不知何故在调用函数main时validate,它const char&甚至在参数出现时都不会使用第二个函数(即函数)char.任何人都可以看到我的问题在哪里?
假设我尝试使用奇怪的重复模板模式创建自己的 boost::filesystem::path 实现:
g++ -std=c++11 -o mypath ./mypath.cpp(为简洁起见,代码不完整,但使用 GCC 4.8.4与“ ”编译时会出现所述问题)
mypath.hpp:
#ifndef MYPATH_HPP
#define MYPATH_HPP
#include <string>
#include <vector>
namespace my {
template <class T>
class PathBase
{
public:
PathBase();
PathBase(std::string const& p);
std::string String() const;
bool IsSeparator(char c) const;
std::string Separators() const;
typedef std::vector<std::string> pathvec;
protected:
pathvec _path;
private:
virtual std::string _separators() const =0;
};
class Path : public PathBase<Path>
{
public:
Path();
Path(std::string const& p);
private:
virtual std::string _separators() const final;
};
} // namespace …Run Code Online (Sandbox Code Playgroud) 如果我编译以下代码:
//
// g++ static.cpp -o static.o
// ar rcs libstatic.a static.o
//
#include <iostream>
template < typename T >
struct TemplatedClass
{
void Test( T value )
{
std::cout << "Foobar was: " << value << std::endl;
}
};
template struct TemplatedClass < long >;
Run Code Online (Sandbox Code Playgroud)
我得到一个静态库,如果我在库上运行nm,我会得到以下结果:
testcase% nm libstatic.a | c++filt | grep TemplatedClass
0000000000000207 s global constructors keyed to _ZN14TemplatedClassIlE4TestEl
0000000000000300 s global constructors keyed to _ZN14TemplatedClassIlE4TestEl.eh
0000000000000118 T TemplatedClass<long>::Test(long)
00000000000002a0 S __ZN14TemplatedClassIlE4TestEl.eh
Run Code Online (Sandbox Code Playgroud)
但是,如果我编译以下代码,除了我添加了模板化类的显式特化之外,它是相同的...
//
// g++ static.cpp …Run Code Online (Sandbox Code Playgroud) 在最近的讨论中,问题是我们是否应该始终完全限定类定义中当前类的名称,并且在引用当前模板本身时也使用显式专用模板.把它们加起来:
namespace foo {
struct Foo {
doSomething(foo::Foo& other); // arguably good
doSomething(Foo& other); // arguably bad
};
}
template<typename T>
struct Bar {
doSomething(Bar<T>& other); // arguably good
doSomething(Bar& other); // arguably bad
};
Run Code Online (Sandbox Code Playgroud)
问题是,没有人可以用严格的事实来支持他们的主张,它只是" 名称查找可能出错 "而不是" meh,从来没有任何问题 ".
为了解决这个问题:这两个约定是否严格等同,或者"坏"有时会在名称查找中引入含糊之处?参考现行标准将是非常好的.
当然,不应该考虑易读性的论点,我真的在询问符合标准的编译器在极端情况下的表现.但是,已知的实现错误也是受欢迎的.
c++ fully-qualified-naming language-lawyer explicit-specialization
出于可读性原因,我想专门化一个接近在命名空间内声明的类的定义的函数模板:
#include <iostream>
template<typename T> void my_function() {
std::cout << "my_function default" << std::endl;
}
namespace Nested {
class A {};
template<> void my_function<A>() {
std::cout << "my_function specialization for A" << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,使用上面的代码,我从 clang++ 4.0 得到以下错误:
error: no function template matches function template specialization 'my_function'
Run Code Online (Sandbox Code Playgroud)
这似乎是一个命名空间问题。我怎样才能使上述工作(不将模板函数专业化移出Nested命名空间)?
编辑:我也尝试添加::my_function专业化:
test.cpp: error: definition or redeclaration of 'my_function' cannot name the global scope
template<> void ::my_function<A>() {
~~^
Run Code Online (Sandbox Code Playgroud) c++ templates namespaces template-specialization explicit-specialization
这是由动机此文章(第5页)
template<class T>
T const &f(T const &a, T const &b){
return (a > b ? a : b);
}
template int const &f<int>(int const &, int const &);
int main(){
int x = 0, y = 0;
short s = 0;
f(x, y); // OK
f(x, s); // Is this call well-formed?
}
Run Code Online (Sandbox Code Playgroud)
通话是否'f(x, s)'良好?我假设由于函数模板'f'是显式实例化的,因此'short s'将应用标准转换,因此将转换'int'为匹配对显式特化的调用'f<int>'.但似乎这是不正确的?
标准的哪一部分谈到了这方面的适用规则?
我正在尝试以下...
#include <iostream>
using namespace std;
template<class T>
class Singleton
{
private:
class InstPtr
{
public:
InstPtr() : m_ptr(0) {}
~InstPtr() { delete m_ptr; }
T* get() { return m_ptr; }
void set(T* p)
{
if (p != 0)
{
delete m_ptr;
m_ptr = p;
}
}
private:
T* m_ptr;
};
static InstPtr ptr;
Singleton();
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
public:
static T* instance()
{
if (ptr.get() == 0)
{
ptr.set(new T());
}
return ptr.get();
}
};
class ABC
{ …Run Code Online (Sandbox Code Playgroud) c++ templates definition template-specialization explicit-specialization