问题与朋友模板函数clang ++ / msvc ++和enable_if [英] Issue with friend template functions clang++ / msvc++ and enable_if

查看:290
本文介绍了问题与朋友模板函数clang ++ / msvc ++和enable_if的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在clang ++中遇到了一个编译器错误。 MSVC ++很高兴。我相信我的声明是正确的。

I get a compiler error in clang++. MSVC++ is happy. I believe my declarations are correct.

我在我的信念不正确,我在MSVC幸运
是否有非 #ifndef _MSC_VER ... public:让这两个编译器都工作?

Am I incorrect in my beliefs and I am "lucky" in MSVC? Is there a non #ifndef _MSC_VER ... public: way to make this work in both compilers?

我想保持构造函数私有。真正的代码稍微复杂一些。 (附加模板元编程和完美转发)以下是针对问题的一个精简版本,并尽可能地隔离问题。我已经尝试了朋友声明的一些变体。在示例中显示了似乎最好的示例。

I'd like to keep the constructor private. The real code is slightly more complex. (additional template meta-programming and "perfect forwarding") The following is a distilled version for the question and to isolate the issue as much as possible. I've tried a number of variations for the friend declaration. The one that "seems best" is shown in the example.

#include<type_traits>

template<typename T> class Wrap;

template<typename T, 
    typename std::enable_if<std::is_class<T>::value, T>::type* = nullptr >
Wrap<T> make_wrapper( T i )
{
    return Wrap<T>( i );
}

template<typename T>
class Wrap : T
{
    friend Wrap<T> make_wrapper<T,nullptr>( T );
private:
    Wrap( T v ) : T( v ) {}
};

template<typename T>
class Imp
{
    T x;
public:
    Imp( T v ) {}
};

int main()
{
    auto wrap = make_wrapper( Imp<int>( 1 ) );
    return 0;
}

clang ++:

$ clang++ --version
Debian clang version 3.5-1~exp1 (trunk) (based on LLVM 3.5)
Target: x86_64-pc-linux-gnu
Thread model: posix

$ clang++ -std=c++11 test.cpp
test.cpp:8 : 12 : error : calling a private constructor of class 'Wrap<Imp<int> >'
return Wrap<T>( i );
^
test.cpp:30 : 17 : note : in instantiation of function template specialization 'make_wrapper<Imp<int>, nullptr>' requested here
auto wrap = make_wrapper( Imp<int>( 1 ) );
^
test.cpp:16 : 5 : note : declared private here
Wrap( T v ) : T( v ) { }
^
1 error generated.

cl

Microsoft Visual Studio Professional 2013
Version 12.0.30501.00 Update 2

1>------ Build started: Project: Test1, Configuration: Debug Win32 ------
1>  Test1.cpp
1>  Test1.vcxproj -> C:\cygwin64\home\username\Test1\Debug\Test1.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========


推荐答案

模板朋友是 臭名昭着的复杂 。我不知道Clang是否是正确的,但它可能是你的SFINAE的函数模板参数内运行

Template friends are notoriously complicated. I don't know for sure whether Clang is right, but it could be that your SFINAE trick inside the function template arguments runs afoul of

14.5.4朋友[temp.friend]


9当朋友声明引用函数
模板的特殊化时,函数参数声明不包括
默认参数
,也不应在这样的
声明中使用内联说明符。

9 When a friend declaration refers to a specialization of a function template, the function parameter declarations shall not include default arguments, nor shall the inline specifier be used in such a declaration.

C ++ 11引入了函数模板的默认模板参数,可能是clang将上面的解释为g ++ / MSVC。它可以通过在返回类型上做SFINAE修复:

C++11 introduced default template arguments for function templates, and it could be that clang interprets the above differently as g++/MSVC. It is fixable by doing SFINAE on the return type instead:

#include<type_traits>

template<typename T> class Wrap;

template<typename T>
using WrapRet = typename std::enable_if<std::is_class<T>::value, Wrap<T>>::type;

template<typename T>
WrapRet<T> make_wrapper( T i )
{
    return Wrap<T>( i );
}

template<typename T>
class Wrap : T
{
    friend WrapRet<T> make_wrapper<T>( T );
private:
    Wrap( T v ) : T( v ) {}
};

template<typename T>
class Imp
{
    T x;
public:
    Imp( T v ) {}
};

int main()
{
    auto wrap = make_wrapper( Imp<int>( 1 ) );
    return 0;
}

活动示例

这篇关于问题与朋友模板函数clang ++ / msvc ++和enable_if的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆