locked
Function overloading with restrict in C++ AMP and namespaces RRS feed

  • Question

  • So I read the article here http://blogs.msdn.com/b/nativeconcurrency/archive/2012/03/29/function-overloading-with-restrict-in-c-amp.aspx that was very useful.

    However I had an issue with overloading and restrict when namespaces are used. I was using the erfc function which is in Concurrency::precise_math but not in the VS12 standard C++ library yet. So I was going to implement my own for restrict(cpu) and then write a restrict(amp,cpu) function that would call either depending on restriction. So the following

    #include <amp_math.h>

    using namespace concurrency::precise_math;

    double erfc( double x )
    {
        return( x * 100.0 );  // Do something useful in reality
    }

    double foo( double x ) restrict(amp,cpu)
    {
        double y = erfc( x );
     
        return( y );
    }

    compiled fine. However the following

    #include <amp_math.h>

    using namespace concurrency::precise_math;

    namespace Bar
    {

    double erfc( double x )
    {
        return( x * 100.0 );
    }

    double foo( double x ) restrict(amp,cpu)
    {
        double y = erfc( x );
     
        return( y );
    }

    }

    which just has the extra namespace added gives the following error

    error C3930: 'Bar::erfc' : no overloaded function has restriction specifiers that are compatible with the ambient context 'Bar::foo'

    Which I think seems to be wrong as foo should still be able to find both the amp and the cpu restricted versions of erfc.

    Note that If I move my restrict(cpu) erfc outside of the Bar namespace and leave foo inside it compiles fine. This seems to imply foo isn't looking up the erfc restrict(cpu) variant correctly. It also causes a lot of problem because I can't start writing all my low level functions in the global namespace!

    Sunday, October 21, 2012 6:36 PM

Answers

  • Hi David!

    The problem you are running into is name hiding - your Bar::erfc declaration effectively hides all erfc names from outside of the Bar namespace. To use both functions in Bar, you have to reintroduce the hidden name with a using declaration. Please see the following example.

    #include <amp_math.h>
    
    namespace N
    {
    	// Define my own cpu-restricted overload
    	double erfc(double) restrict(cpu)
    	{
    		return 0;
    	}
    
    	// Re-introduce the hidden amp-restricted overload
    	using concurrency::precise_math::erfc;
    
    	// Verify
    	void test() restrict(cpu,amp)
    	{
    		erfc(3.14);
    	}
    }

    Please note that this behavior is not specific to C++ AMP - we were aligning our rules to the standard C++. This case is analogous to declaring an overloaded function with a different number or types of parameters - the "external" one would have to be similarly "unhidden" with the using declaration.

    • Proposed as answer by Don McCrady Monday, October 22, 2012 4:28 PM
    • Marked as answer by Amit K Agarwal Thursday, January 3, 2013 12:41 AM
    Sunday, October 21, 2012 8:03 PM