Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Templates 好友模板函数出现问题&x2B+;/msvc&x2B+;并在以下情况下启用_Templates_Visual C++_C++11_Friend_Clang++ - Fatal编程技术网

Templates 好友模板函数出现问题&x2B+;/msvc&x2B+;并在以下情况下启用

Templates 好友模板函数出现问题&x2B+;/msvc&x2B+;并在以下情况下启用,templates,visual-c++,c++11,friend,clang++,Templates,Visual C++,C++11,Friend,Clang++,我在clang++中遇到一个编译器错误。MSVC++很高兴。我相信我的声明是正确的 我的信念是错误的,我在MSVC是“幸运的”吗? 是否有非\ifndef\u MSC\u版本。。。public:如何在两种编译器中都实现此功能 我想把构造函数保密。真正的代码稍微复杂一些。(附加模板元编程和“完美转发”)以下是问题的提炼版本,以尽可能隔离问题。我已经尝试了朋友声明的多种变体。示例中显示了“似乎最好”的一个 #include<type_traits> template<typena

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

我的信念是错误的,我在MSVC是“幸运的”吗? 是否有非
\ifndef\u MSC\u版本。。。public:
如何在两种编译器中都实现此功能

我想把构造函数保密。真正的代码稍微复杂一些。(附加模板元编程和“完美转发”)以下是问题的提炼版本,以尽可能隔离问题。我已经尝试了朋友声明的多种变体。示例中显示了“似乎最好”的一个

#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是否正确,但可能是函数模板参数中的SFINAE技巧与

14.5.4朋友[临时朋友]

9当友元声明引用函数的特殊化时 模板,函数参数声明不应包括 默认参数,在这种情况下也不能使用内联说明符 声明

C++11为函数模板引入了默认模板参数,可能是clang将上述参数解释为g++/MSVC。可以通过对返回类型执行SFINAE来解决此问题:

#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;
}
#包括
模板类包装;
模板
使用WrapRet=typename std::enable_if::type;
模板
WrapRet make_包装器(TI)
{
退货包装(一);
}
模板
课程名称:T
{
friend WrapRet make_wrapper(T);
私人:
包裹(tv):T(v){}
};
模板
类Imp
{
tx;
公众:
Imp(tv){}
};
int main()
{
自动包装=制作包装(Imp(1));
返回0;
}

这对clang和g++都适用。

FWIW,g++4.8.2认为您的代码很好。感谢我~应该~检查一下g++中有问题的代码。如果我不让太多额外的怪癖渗透到代码中,我怀疑这会在将来节省我的时间。到目前为止,我一直在避免在这方面花费太多时间。我想现在是将g++添加到列表中的时候了。当然,它~将~用于简单的孤立案例!谢谢你的主意!在非隔离代码的“真实世界”中,我避免将声明移动到返回类型或作为参数,因为生成的代码更难读取。当我尝试(刚才)将enable_if移动到返回类型时,我得到了其他有趣的错误。(我将在后面讨论。)我过去喜欢模板,但哇哦,C++11模板元语法可能有点太多了。@ErnieE和一些助手类型,如
WrapRet
可读性应该保持正常。如果您的实际测试仍然无法完成,那么期待减少测试用例使用“using”是唯一一个让其他方面变得一团糟的东西(IMO:记住,我真的很喜欢模板)。私有构造函数现在可以工作了,但我没有时间追踪是什么绊倒了另一个成员,我想保持私有。我不知道enable_if构造会在助手中起作用。在不久的将来,我肯定会(在适当的情况下)提出一些其他声明。如果您感兴趣,该项目位于[链接]上,谢谢您的帮助。@ErnieE是的,模板别名是SFINAE友好的,它们不会引入新类型,只是引入别名,而且
std::enable_If
实际上是直接在返回类型中编写的。在C++14中,
中的所有当前特征将获得
sometrait\u t
版本,其中
\u t
后缀表示:
typename sometrait::type
。甚至有人建议添加
\u v
后缀来执行
::value
提取。因此,您可以(2017年及以后)直接编写
std::enable_if_t
:-)我还与其他成员一起解决了我想要保密的问题。切换编译器产生了“duh”时刻。一般来说,clang++提供了更好的诊断,但在本例中,MSVC直接向我指出了这个问题,而clang++则缺乏。我一直期待着化名。常量别名也非常有用。从一开始('94!),我几乎总是对大多数模板使用typedef。有些人抱怨typedef是混淆。我更喜欢表达的简单<代码>使用是我最喜欢的第二个参数包。
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 ==========
#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;
}