我正在尝试使用模板函数返回模板类构造函数中参数的默认值。函数的模板参数也是类的模板参数。我在下面提供了一个示例。
背景 该示例显示了确切的用例和依赖项,因为它们也出现在我的应用程序中。 X 类实际上是一个相当大的类,它管理一个大数据 block ,该大数据 block 被分成更小的 block 。类助手是一个内存管理器,它以较小的 block 大小分配和释放内存。实际上,GetHelper 函数会在运行时尝试推导出 Helper 的一些构造函数参数,所以这就是我使用这种设计的原因。
实际问题 当定义了宏 USE_NS 和 SHOW_ERROR 时,代码无法编译,在第 66 行给出错误 C2783 无法推断模板参数。这是我尝试使用模板函数初始化构造函数参数的地方GetHelper(提供模板参数!)。请记住,GetHelper 来自与类 X 不同的 namespace 。还请注意,在第 72 行中使用了相同的函数调用来初始化构造函数体内的 Helper 对象。怎么了?有解决方案或解决方法吗?
我正在使用 Visual Studio 2008 Pro 和 boost 1.47。
#include <iostream>
#include <boost/shared_ptr.hpp>
// 1 means macro is defined
// USE_NS 1 and SHOW_ERROR 1 -> Compileerror
// USE_NS 0 and SHOW_ERROR 1 -> Works, Output: 8 and 16.5
// USE_NS 1 and SHOW_ERROR 0 -> Works, Output: 3
// USE_NS 0 and SHOW_ERROR 0 -> Works, Output: 3
#define USE_NS
#define SHOW_ERROR
#ifndef USE_NS
#define NH
#define NX
#endif
#ifdef USE_NS
namespace NH
{
#endif
template< typename TNumAtH, size_t TSizeAtH>
class Helper
{
public:
TNumAtH* x;
Helper()
{
x = new TNumAtH[TSizeAtH];
x[0] = static_cast< TNumAtH >( 8 );
}
~Helper()
{
delete [] x;
}
};
template <typename TNumAtF, size_t TSizeAtF >
boost::shared_ptr< Helper< TNumAtF, TSizeAtF > > GetHelper()
{
return boost::shared_ptr< Helper< TNumAtF,TSizeAtF > > ( new Helper< TNumAtF, TSizeAtF >() );
}
#ifdef USE_NS
}
namespace NX
{
#endif
template< typename TNumAtX, size_t TSize >
class X
{
public:
boost::shared_ptr< NH::Helper< TNumAtX, TSize > > a;
#ifdef SHOW_ERROR
//this produces an error if namespace are used, if no namespaces are used
//NH is reduced to a blank (see macros at line 17 and 18
X( boost::shared_ptr< NH::Helper< TNumAtX, TSize > > h = NH::GetHelper< TNumAtX, TSize >() );
#endif
X( TNumAtX firstElem )
{
//this works with namespaces and without namespaces
a = NH::GetHelper< TNumAtX, TSize >();
a->x[0] = firstElem;
}
TNumAtX GetNum()
{
return a->x[0];
}
};
#ifdef SHOW_ERROR
template< typename TNumAtX, size_t TSize >
X<TNumAtX, TSize>::
X( boost::shared_ptr< NH::Helper< TNumAtX, TSize > > h ) : a( h )
{
}
#endif
#ifdef USE_NS
}
#endif
int main( int argc, char** argv )
{
std::cout << "Hello at TestTemplateFunction" << std::endl;
//use case one
#ifdef SHOW_ERROR
NX::X<int, 5> x1;
#else
NX::X<int, 5> x1( 3 );
#endif
std::cout << "Use case 1: " << x1.GetNum() << std::endl;
//use case two
#ifdef SHOW_ERROR
typedef float T;
size_t const N = 9;
boost::shared_ptr< NH::Helper<T, N> > h( new NH::Helper<T, N> );
h->x[0] = 16.5f;
NX::X<T, N> x2( h );
std::cout << "Use case 2: " << x2.GetNum() << std::endl;
#endif
std::cout << "Hit the any key" << std::endl;
getchar();
return 0;
}
这是 CMakeLists.txt 文件
PROJECT(TestTemplateFunction)
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
FIND_PACKAGE( BOOST )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
ADD_EXECUTABLE( TestTemplateFunction main.cpp )
编辑:编译错误
main.cpp(65) : error C2783: 'boost::shared_ptr<NH::Helper<TNumAtH,TSizeAtH>> NH::GetHelper(void)' : could not deduce template argument for 'TNumAtF'
main.cpp(44) : see declaration of 'NH::GetHelper'
main.cpp(65) : error C2783: 'boost::shared_ptr<NH::Helper<TNumAtH,TSizeAtH>> NH::GetHelper(void)' : could not deduce template argument for 'TSizeAtF'
main.cpp(44) : see declaration of 'NH::GetHelper'
最佳答案
突发新闻
在 Clang 3.2 上报告该问题后,看来这实际上是一个 C++ 缺陷。你看到 bug discussion in the clang database .
引用理查德·史密斯的话:
This is a defect in C++ itself:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#325
Clang matches the behavior of all other C++ compilers here; this is not a bug (though depending on the way in which that issue is resolved, we may need to revisit this).
The workaround is to add parentheses around the default argument expression.
问题是歧义之一。例如,通过查看:
int = a < b, c < d > ( e )
...是一个参数,并且...
int = a < b, c < d > ( e ) = 0
我们可以体会到模板参数之间不容易区分,正则<调用以及因此构成默认参数的内容。
如果我们遵循 Richard 的建议并添加括号,那么我们将不再受制于编译器的突发奇想。或者至少,I can guarantee Clang gets it right (修订版 6):
X( boost::shared_ptr< NH::Helper<T, N> > h = (NH::GetHelper<T, N>()) );
在我看来这像是一个编译器错误。
我测试了您的代码(感谢您顺便发布了一个完整的示例)on liveworkspace gcc 4.7.2 产生以下输出:
Hello at TestTemplateFunction
Use case 1: 8
Use case 2: 16.5
当 clang 3.2 产生时:
Compilation finished with errors:
source.cpp:65:86: error: unknown type name 'TSize'
X( boost::shared_ptr< NH::Helper< TNumAtX, TSize > > h = NH::GetHelper< TNumAtX, TSize >() );
^
source.cpp:65:92: error: expected ')'
X( boost::shared_ptr< NH::Helper< TNumAtX, TSize > > h = NH::GetHelper< TNumAtX, TSize >() );
^
source.cpp:65:6: note: to match this '('
X( boost::shared_ptr< NH::Helper< TNumAtX, TSize > > h = NH::GetHelper< TNumAtX, TSize >() );
^
source.cpp:65:84: error: expected '>'
X( boost::shared_ptr< NH::Helper< TNumAtX, TSize > > h = NH::GetHelper< TNumAtX, TSize >() );
^
source.cpp:85:1: error: out-of-line definition of 'X<TNumAtX, TSize>' does not match any declaration in 'X<TNumAtX, TSize>'
X( boost::shared_ptr< NH::Helper< TNumAtX, TSize > > h ) : a( h )
^
4 errors generated.
我以两种方式稍微修改了示例(更改 5):
介绍static boost::shared_ptr<Helper> Get() { return boost::shared_ptr<Helper>(new Helper()); }内嵌在 Helper 中模板
做了一个typedef NH::Helper< TNumAtX, TSize > Helper在 X并将其用于构造函数 X(boost::shared_ptr<Helper> h = Helper::Get());
现在 clang 设法编译了代码。
我设法将(clang 的)错误减少到:
template <typename T, unsigned N>
struct Helper {};
template <typename T, unsigned N >
Helper< T, N > GetHelper() { return Helper< T, N > (); }
template < typename T, unsigned N >
struct X {
X( Helper< T, N > h = GetHelper<T, N>() ) {}
};
你可以see it here .
关于c++ - Visual C++ 无法推断在 ctor 中用作默认值的函数的给定(!)模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14401308/
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e
我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re