在本文中,关于::std::error_code
为作者定义自己的扩展,建议使用以下代码:
namespace std
{
template <>
struct is_error_code_enum<http_error>
: public true_type {};
}
Run Code Online (Sandbox Code Playgroud)
为了实现从您自己的错误常量到系统错误类型的转换.
这合理吗?将东西放入std
命名空间总是让我感到紧张.有没有更好的方法来实现目标?如果做不到这一点,标准的一部分是否可以做到这一点?
我有代码:
#include <cstdio>
template<template<typename...> class>
struct Foo
{
enum { n = 77 };
};
template<template<typename, typename...> class C>
struct Foo<C>
{
enum { n = 99 };
};
template<typename...> struct A { };
template<typename, typename...> struct B { };
int main(int, char**)
{
printf("%d\n", Foo<A>::n);
printf("%d\n", Foo<B>::n);
}
Run Code Online (Sandbox Code Playgroud)
这个想法是它template<typename, typename...> class
的一个子集template<typename...> class
,因此有可能专注于它.但它非常深奥,所以也许不是.我们来试试吧.
GCC 4.7说:
$ g++ -std=c++11 test157.cpp
Run Code Online (Sandbox Code Playgroud)
它汇编了!
运行它:
$ ./a.out
77
99
Run Code Online (Sandbox Code Playgroud)
有用!
Clang 3.1说:
$ clang++ -std=c++11 test157.cpp
test157.cpp:10:8: error: class template …
Run Code Online (Sandbox Code Playgroud) c++ templates template-specialization variadic-templates c++11
C++标准禁止朋友声明部分特化.(§14.5.3/ 8):
朋友声明不得声明部分专业化.[例:
template<class T> class A { };
class X {
template <class T> friend class A<T*>; //error
};
Run Code Online (Sandbox Code Playgroud)
- 末端示例]
其他问题,例如这个问题,已经收到了援引这一禁令的答案,但我想知道其基本原理.我没有看到它,也无法用我最喜欢的搜索引擎找到它.然而,我可以发现它可以追溯到C++ 98标准,所以大概是基本的和清晰的.有人可以向我解释一下吗?
template<class> struct Printer;
// I want this to match std::vector (and similar linear containers)
template<template<class, class...> class T, class TV, class... TS>
struct Printer<T<TV, TS...>> { ... };
// I want this to match std::map (and similar map-like containers)
template<template<class, class, class...> class TM, class TK, class TV, typename... TS>
struct Printer<TM<TK, TV, TS...>> { ... }
int main()
{
// Both of these match the second specialization, which is only intended
// for std::map (and similar map-like containers)
Printer<std::vector<int>>::something(); …
Run Code Online (Sandbox Code Playgroud) 在尝试实现依赖于可变参数模板的一些事情时,我偶然发现了一些我无法解释的事情.我将问题归结为以下代码片段:
template <typename ... Args>
struct A {};
template <template <typename...> class Z, typename T>
struct test;
template <template <typename...> class Z, typename T>
struct test<Z, Z<T>> {
static void foo() {
std::cout << "I'm more specialized than the variadic spec, hehe!" << std::endl;
}
};
template <template <typename...> class Z, typename T, typename ... Args>
struct test<Z, Z<T, Args...>> {
static void foo() {
std::cout << "I'm variadic!" << std::endl;
}
};
int main() {
test<A, A<int>>::foo();
}
Run Code Online (Sandbox Code Playgroud)
在gcc下,它会产生错误,因为它在尝试实例化时认为两个特化都是同样专业的 …
c++ template-specialization language-lawyer variadic-templates c++11
#include <iostream>
#include <array>
#include <vector>
template <typename T, typename SFINAE=void>
struct trait;
template <typename T>
struct trait<T, decltype(
std::declval<const T&>().begin(),
std::declval<const T&>().end(),
void()
)> {
static const char* name() { return "Container"; }
};
template <typename T, std::size_t N>
struct trait<std::array<T,N>> {
static const char* name() { return "std::array"; }
};
int main(int argc, char* argv[]) {
std::cout << trait<std::vector<int>>::name() << std::endl;
std::cout << trait<std::array<int,2>>::name() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我期待第三个模板比第二个模板更专业,但我得到了一个模糊的模板实例化.
有没有办法让第三个模板更专业?明确检查是否T
是std::array
在第二个模板不会为我工作.我正在写一个图书馆,希望用户能够定义他们自己的专业trait
.第二个模板旨在成为没有更具体特征的容器的通用特化.
I don't understand the following behavior.
The following code, aimed at computing the factorial at compile time, doesn't even compile:
#include <iostream>
using namespace std;
template<int N>
int f() {
if (N == 1) return 1; // we exit the recursion at 1 instead of 0
return N*f<N-1>();
}
int main() {
cout << f<5>() << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
and throws the following error:
...$ g++ factorial.cpp && ./a.out
factorial.cpp: In instantiation of ‘int f() [with int N = …
Run Code Online (Sandbox Code Playgroud) 给定以下类模板:
template<typename T>
struct Outer
{
struct Inner;
auto f(Inner) -> void;
};
Run Code Online (Sandbox Code Playgroud)
我们Inner
为以下每种专业分别定义Outer
:
template<>
struct Outer<int>::Inner {};
template<>
struct Outer<double>::Inner {};
Run Code Online (Sandbox Code Playgroud)
然后f
为以下所有专业定义一次成员函数Outer
:
auto Outer<T>::f(Inner) -> void
{
}
Run Code Online (Sandbox Code Playgroud)
但是Clang(9.0.0)抱怨:
error: variable has incomplete type 'Outer::Inner'
auto Outer<T>::f(Inner) -> void
^
Run Code Online (Sandbox Code Playgroud)
我们还可以通过提供Inner
以下所有其他专业的定义来规避编译器错误Outer
:
template<typename T>
struct Outer<T>::Inner {};
Run Code Online (Sandbox Code Playgroud)
或通过f
为每个专业分别定义:
template<>
auto Outer<int>::f(Inner) -> void
{
}
template<>
auto Outer<double>::f(Inner) -> void
{
}
Run Code Online (Sandbox Code Playgroud)
GCC和MSVC都接受初始代码,这就是问题所在。这是Clang错误,还是这三个中唯一的一致实现?
c++ templates template-specialization language-lawyer incomplete-type
我正在编写一个带有模板矢量类型的简单数学库:
template<typename T, size_t N>
class Vector {
public:
Vector<T, N> &operator+=(Vector<T, N> const &other);
// ... more operators, functions ...
};
Run Code Online (Sandbox Code Playgroud)
现在我想要一些专门用于其中一些功能的附加功能.比方说,我想要的功能x()
,并y()
在Vector<T, 2>
访问特定的坐标.我可以为此创建一个部分特化:
template<typename T>
class Vector<T, 3> {
public:
Vector<T, 3> &operator+=(Vector<T, 3> const &other);
// ... and again all the operators and functions ...
T x() const;
T y() const;
};
Run Code Online (Sandbox Code Playgroud)
但现在我正在重复通用模板中已存在的所有内容.
我也可以使用继承.将通用模板重命名为VectorBase
,我可以这样做:
template<typename T, size_t N>
class Vector : public VectorBase<T, N> {
};
template<typename T> …
Run Code Online (Sandbox Code Playgroud) 我有以下示例,我已经从中分解§14.7.3/6 [temp.expl.spec]
了在主模板中定义类成员枚举,然后专门化它.以下内容不能在clang中编译:
template<class T>
struct A {
enum E : T;
};
template<class T>
enum A<T>::E : T { eT };
template<>
enum A<char>::E : char { echar }; // ill-formed, A<char>::E was instantiated
// when A<char> was instantiated
// error: explicit specialization of 'E' after instantiation
Run Code Online (Sandbox Code Playgroud)
原因应该是在专门化之前实例化未编组成员枚举的定义.14.7.1 [temp.inst]/1:
类模板特化的隐式实例化导致隐式实例化未编组成员枚举和成员匿名联合的定义.
我试图理解为什么这是一个问题.是因为如果枚举已经有了定义,那么在专门化期间会导致重新定义错误吗?