我有一个模板化的类A
和一个模板化函数f
,它返回A
个对象。我希望f<T>
成为A<T>
的朋友,仍然是constexpr
template <typename T>
class A;
template <typename T>
constexpr A<T> f();
//f<T> is a friend of A<T>
template <typename T>
class A {
friend /* constexpr? */ A f<T>();
constexpr A() {}
};
template <typename T>
constexpr A<T> f() { return {}; }
int main() {
constexpr auto a = f<void>();
}
我不能让clang和gcc同意这里的内容。如果我没有将constexpr
放在朋友声明中,gcc工作正常但是clang不会编译它,错误地用:
main.cpp:18:18: error: constexpr variable 'a' must be initialized by a constant expression
constexpr auto a = f<void>();
^ ~~~~~~~~~
main.cpp:18:23: note: non-constexpr function 'f<void>' cannot be used in a constant expression
constexpr auto a = f<void>();
^
main.cpp:9:12: note: declared here
friend A f<T>();
如果我在朋友声明中将其标记为constexpr
,则clang编译正常但gcc会给我错误:
main.cpp:9:27: error: 'constexpr' is not allowed in declaration of friend template specialization 'A<T> f<T>()'
friend constexpr A f<T>();
我怎样才能让每个人都开心?
答案 0 :(得分:6)
int main() { constexpr auto a = f<void>(); }
这将功能模板f
专门化为函数f<void>()
;在f
的特化期间,编译器还尝试实例化A<void>
,friend f<void>()
反过来声明专门化constexpr
。
这两个声明必须匹配constexpr
:
[dcl.constexpr] / 1
[...]如果函数或函数模板的任何声明都有
constexpr
说明符,那么它的所有声明都应包含constexpr
说明符。 [注意:显式特化可能与constexpr
说明符的模板声明不同。 - 结束记录]
如果你在friend
声明中省略constexpr
而不是删除看似非constexpr
函数的内容,那么Clang可能会错误地输出错误,但至少它接受了正确的语法。
Gcc不应该允许该版本丢失constexpr
,并且由于bug而提供constexpr
时会出错。这已经在主干中得到修复,我现在可以确认它是有效的,但是当var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
require('mongoose-middleware').initialize(mongoose);
mongoose.connect('mongodb://localhost/test');
var testSchema = new Schema({
a: Number,
b: Number,
c: Number
});
var Test = mongoose.model( 'Test', testSchema );
async.series(
[
function(callback) {
Test.remove({},callback);
},
function(callback) {
async.each(
[
{ a: 1, b: 2, c: 3 },
{ a: 2, b: 1, c: 4 },
{ a: 4, b: 3, c: 1 },
{ a: 2, b: 2, c: 1 }
],
function(item,callback) {
Test.create(item,callback);
},
callback
);
},
function(callback) {
Test.find().sort("a -b c").page({
start: 0,
count: 3
},function(err,docs) {
console.log(docs);
callback(err);
});
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);
丢失时它仍然没有提供错误。