以下代码使用g ++ 4.8.1成功编译:
int main()
{
int(*)();
}
Run Code Online (Sandbox Code Playgroud)
它看起来像一个函数指针的简单声明:
int(*f)();
Run Code Online (Sandbox Code Playgroud)
它不能用clang 3.4和vc ++ 2013编译.
它是编译器错误还是标准的黑暗之处?
int(*)();
int(*);
int(*){};
int(*());
更新1: @Ali在评论中添加了一些有趣的信息:
所有4个案例都使用clang 3.5 trunk(202594)进行编译错误,并使用gcc 4.9 trunk(20140302)进行编译.行为是一样的
-std=c++98 -pedantic,除了int(*){};可以理解的; 扩展初始化程序列表仅适用于-std=c++11.
更新2:正如@CantChooseUsernames在他的回答中指出的那样,即使没有任何启用的优化,即使初始化它们仍然可以正常编译并且没有为它们生成汇编(无论是否初始化):
int(*)() = 0;
int(*) = 0;
int(*){} = 0;
int(*()) = 0;
更新3:我真的很惊讶地发现int(*)() = "Hello, world!";编译也很好(int(*p)() = "Hello, world!";当然不会编译).
更新4:太棒了但int(*){} = Hello, world!;编译得很好.而下面的怪异之极的一段代码,也:int(*){}() …
考虑以下类模板"X"及其部分特化.
template <class ...Types>
struct X {}; // #1
template <class T1>
struct X<T1> {}; // #2
template <class T1, class ...Types>
struct X<T1, Types...> {}; // #3
X<int> x; // #2 or #3 ?
Run Code Online (Sandbox Code Playgroud)
我怀疑X <int>是不明确的.这是因为:
很明显,#2和#3都比#1更专业,现在比较#2和#3.根据14.5.5.2,让我们考虑以下哪个#2'和#3'更专业.
template <class T1>
void f(X<T1>); // #2'
template <class T1, class ...Types>
void f(X<T1, Types...>); // #3'
Run Code Online (Sandbox Code Playgroud)
根据14.8.2.4,第一步是模板参数推导,使用#2'作为参数模板,#3'作为参数模板.给定唯一的参数类型是X <A1>,推导出的T1是A1,而Types是空的.
A = X<A1>, P = X<T1, Types...> => T1 = A1, Types = {}
Run Code Online (Sandbox Code Playgroud)
第二步是使用#3'作为参数模板,使用#2'作为参数模板.鉴于唯一的参数类型是X <A1,Args ...>,根据14.8.2.5/9(注意该段最近由N3281修订),Args被简单地忽略,推断的T1是A1并且参数推断成功.
A = X<A1, Args...>, P = …Run Code Online (Sandbox Code Playgroud) c++ templates template-specialization variadic-templates c++11
以下代码在C++中是否有效?
int main() noexcept
{
}
Run Code Online (Sandbox Code Playgroud)
既铛++ 3.8.0和克++ 7.2.0 编译它细(与-std=c++14 -O0 -Wall -Wextra -Werror -pedantic-errors编译标志).
是否允许在函数规范中使用复杂条件(例如包括noexcept运算符)?noexceptmain
那么C++ 17呢?据我所知,noexcept说明符成为本标准修订版中函数类型的一部分.
当使用vim插件YouCompleteMe进行C++代码完成时,我偶然发现了一个问题.使用嵌套模板类可以使完成无法正常工作.
请考虑以下示例来重现行为:
#include <vector>
template<class T>
class foo {
public:
void Init();
private:
struct bar {
int foobar;
};
bar one_bar;
std::vector<foo<T>::bar> some_bars;
};
template<class T>
void foo<T>::Init(){
one_bar.foobar = 0; // completion as expected
some_bars.at(0).foobar = 0; // no completion neither for "at" nor for "foobar"
}
Run Code Online (Sandbox Code Playgroud)
"some_bars"的代码完成根本不起作用,而"one_bar"的行为与预期一致.
如何完成此代码的完成工作?这个问题是否与设置有关并且实际上应该有效还是YCM中的错误?
我的系统是基于debian的jessie/sid,vim版本7.4,来自GitHub的YCM最新版本.
编辑:YCMs bug跟踪器中报告了类似的问题:https : //github.com/Valloric/YouCompleteMe/issues/243 https://github.com/Valloric/YouCompleteMe/issues/530
似乎是铿锵而不是YCM中的错误.有人能证实吗?
编辑2:我在YCM问题跟踪器中打开了另一个问题. https://github.com/Valloric/YouCompleteMe/issues/1170
目的是获得有关clang中的错误信息的更多信息,最后在clang问题跟踪器中进行错误报告.
编辑3:我按照RedX的建议程序,在clang中输入我的代码以获得完成.Clang没有为代码中讨论的位置提供任何建议.这显然是YCM未能在vim中提出建议的原因,它与YCM或vim无关.
已提交clang问题跟踪器中的错误报告:http: //llvm.org/bugs/show_bug.cgi?id = 20973
我一直在使用可变参数模板并注意到以下内容.
这很好用:
auto t = std::make_tuple(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
Run Code Online (Sandbox Code Playgroud)
这将给出错误(gcc 4.8.2(编辑:Clang 3.4)默认最大深度为256):
auto t2 = std::make_tuple(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);
Run Code Online (Sandbox Code Playgroud)
但是,直接创建元组将起作用:
std::tuple<int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int> t3(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);
Run Code Online (Sandbox Code Playgroud)
我在尝试创建一个返回模板化类的模板化函数时注意到了这一点.
template <typename...Arguments>
struct Testing {
std::tuple<Arguments...> t;
Testing(Arguments...args) : t(args...) {}
};
template <typename... Arguments>
Testing<Arguments...> create(Arguments... args) {
return Testing<Arguments...>(args...);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,这将工作:
auto t4 = create(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16);
Run Code Online (Sandbox Code Playgroud)
这不会:
auto t5 = create(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17);
Run Code Online (Sandbox Code Playgroud) 我想创建一个编译类型的函数,给定任何可调用的对象f(函数,lambda表达式,函数对象,...)和类型T,如果f可以使用类型的参数调用,则求值为true,如果是,则为Tfalse这不可以.
例:
void f1(int) { ... }
void f2(const std::string&) { ... }
assert( is_callable_with<int>(f1));
assert(!is_callable_with<int>(f2));
Run Code Online (Sandbox Code Playgroud)
我认为巧妙地使用SFINAE规则可以实现这一目标.可能有点像这样:
template<typename T, typename F>
constexpr bool is_callable_with(F&&, typename std::result_of<F(T)>::type* = nullptr) {
return true;
}
template<typename T, typename F>
constexpr bool is_callable_with(F&&) {
return false;
}
Run Code Online (Sandbox Code Playgroud)
但这不起作用,因为如果F可调用T,则两个重载都参与重载决策并且存在歧义.我想重写它,所以在正面情况下,第一个重载将由第二个重载决策选择.不确定我是否在这里的正确轨道.
我正在使用以下SFINAE模式来评估可变参数类型列表上的谓词:
#include <type_traits>
void f(int = 0); // for example
template<typename... T,
typename = decltype(f(std::declval<T>()...))>
std::true_type check(T &&...);
std::false_type check(...);
template<typename... T> using Predicate = decltype(check(std::declval<T>()...));
static_assert(!Predicate<int, int>::value, "!!");
static_assert( Predicate<int>::value, "!!");
static_assert( Predicate<>::value, "!!"); // fails
int main() {
}
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,选择省略号过载时check被调用空的参数列表,因此Predicate<>是std::false_type即使SFINAE表达是有效的!
variadic函数模板不应该总是优先于省略号函数吗?
有没有解决方法?
如何(如果可能的话)我可以使用c ++ 11可变参数编程来定义vector函数体中的一系列函数(或者换句话说,一个N具有递减N的s 的序列直到0),如下面的变量?
vector<vector<vector<int>>> v<3>;
vector<vector<int>> v<2>;
vector<int> v<1>;
int v<0>;
Run Code Online (Sandbox Code Playgroud)
我想象的是:
#include <iostream>
#include <vector>
using namespace std;
template<int ...> struct seq {};
template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};
template<int ...S> struct gens<0, S...>{ typedef seq<S...> type; };
template<int ...S>
void f(seq<S...>) {
//how do I write definitions of v<N> here?
vector<vector<...(N layers)<vector<int> ...> v<N>; //??how-to, not valid c++
vector<vector<...(N -1 layers)<vector<int> ...> v<N-1>;//??how-to, not valid c++ …Run Code Online (Sandbox Code Playgroud)