2

I'm writing a smart ptr template which is intended to be instantiated only for a given base class and its subclasses, which provides boost::shared_ptr-like implicit conversions to variants MyPtr<U> of the template MyPtr<T> has long as the conversion is valid from T* to U* (valid base class and const-compatible).

This was working fine in vs2005, but not with g++ on linux so my colleague changed it there, but doing so it broke the const-correctness.

My problem is that I want to unit test that some conversions are not valid (assign MyPtr<const T> to MyPtr<T> for example), resulting in the file not compiling! But you can't have a file not compiling in the solution...

If there some VS-specific #pragma or some SFINAE trick that could test a given construct is NOT valid and therefore doesn't compile?

Thanks, --DD

ddevienne
  • 1,802
  • 2
  • 17
  • 28
  • 1
    Can you post some code that is broken? – dirkgently May 12 '09 at 22:56
  • You can check this question I asked about unit testing compile-time error : http://stackoverflow.com/questions/605915/unit-test-compile-time-error – Luc Touraille May 13 '09 at 07:44
  • Thanks for the link Luc. This is indeed in the same spirit as my question. But the answers also leave me wanting for something better. I have a feeling that SFINAE could be of help here somehow, if the code meant not to compile is wrapped in a template, which is later used for function overloading resolution. In this code is *allowed* not to compile for one overload candidate, the default case overload is chosen instead, and that's detectable at runtime. I'm going to try something along these lines when I get the time. – ddevienne May 13 '09 at 13:58

2 Answers2

1

You could run the command line compiler, cl, which is pretty easy to set up, and capture its error message output.

No makefile, and hardly any info from the solution/project. Just the include path and a source file. At it's simplest you just need a program that "reverses" the exit code of another program:

#include <sstream>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    std::ostringstream command;

    for (int n = 1; n < argc; n++)
        command << argv[n] << " ";

    return (system(command.str().c_str()) == EXIT_SUCCESS)
                ? EXIT_FAILURE : EXIT_SUCCESS;
}

It simply reconstitutes the arguments passed to it into (omitting its own name) and exits the resulting command line, and then returns success if it fails and failure if it succeeds. That is enough to fool Visual Studio or make.

Technically the reconstituted command line should quote the arguments, but that will only be necessary if you are insane enough to put spaces in your build directory or source file names!

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
  • I'm looking for something that runs within visual studio, which would be no different than RMB my unit test project in the solution, selecting "Set As Startup Project" and press F5. Having external scripts / makefiles that would duplicate all the build info from the solution isn't really the kind of solution I have in mind, and the reporting in case of failure would likely be external too. – ddevienne May 12 '09 at 22:37
  • You seem to be imagining this will be harder than it really is! See updated answer. It's really simple (much simpler than writing a smart pointer). – Daniel Earwicker May 12 '09 at 23:11
  • I'd rather write smart ptr code (well, actually I'd rather use the Boost ones, but this is a special case here, which in fact uses a shared_ptr inside) rather try to write a cross-platform compiler-forking, output-parsing, program that can work with VS and GCC/make ;-) – ddevienne May 13 '09 at 13:52
  • That's way overboard. The output is merely the exit code. This is a completely trivial problem as far as I can see. I've updated the answer with the necessary code. – Daniel Earwicker May 13 '09 at 15:39
0

If a given argument (in your case 'const T') would satisfy all the other unit tests except this one you're looking for, isn't it the sign that it would be a perfectly acceptable case? In other words, if it works, why forbid it?

Xavier Nodet
  • 5,033
  • 2
  • 37
  • 48
  • Uh. no ;-) If you have a boost::shared_ptr, you can't implicitly convert it to boost::shared_ptr, for the same reasons C++ forbids the same conversion on raw pointers. My situation is the similar, albeit more complex because my smart pointer needs to use boost::mpl to decide which T goes into the shared_ptr (thus the bug, mpl isn't super easy). – ddevienne May 13 '09 at 13:49